canvas上插入图片时跨域和覆盖问题

终于搞定了canvas上插入图片的问题了。

先说说我遇到的问题:

  1. 跨域问题
  2. 多个图片加载问题

跨域问题

  1. 这个好说,首先我们接收到的图片资源必须可以跨域访(Access-Control-Allow-Origi), 然后再img标签中加上crossOrigin = "anonymous", 如果是用JS创建的img(let img = new Image ), 可以使用img.crossOrigiin = true 或者是 "anonymous"都可以,用来设置可以接收到跨域的图片资源

多个图片加载问题

  1. 一个图片都好说,在它的onload事件中 去drawImage,但是多个有图片呢?
  2. 如果不确定各个图片的加载完成顺序,就会导致我不知道应该在哪个图片的onload事件中执行其它操作(写字等)。这时我想到了一个(不太好的)办法:每当onlaod执行时,我给这个图片设置一个flag为true,然后用setInterval()写一个周期函数,周期函数用来监听当所有图片的flag为true时,执行其它操作
  3. 上个方法有个隐藏的坑,当图片存在层次关系式,先draw的图片会覆盖住后draw的图片,所有如果有高宽为canvas高宽的背景图时,我们就必须确保这个背景图最先draw,那么上一个方法就行不通了,因为它无法确定图片的onload事件执行顺序(onload事件中会执行drawImage)
  4. 如果我们要确定onlaod的执行顺序又该如何做呢?这就要想想onload什么时候被触发(img图片加载完成时触发)。所以,如果我们不给img.src赋值(img = new Image),onload事件永远都不会触发,通过这个原理,我们可以在img1的onload事件中去给img2的src赋值(img1.src必须在onload事件外面赋值),这样的设置只有在img1加载完成后,img2才会加载。 不过这样做也有缺点:图片的加载变成了同步,想对于上个方法,时间可能会久点,所以:只有当我们需要加载的多张图片存在覆盖问题时,才来采用这种方法

canvas转化为的图片的预览图:

canvas上插入图片时跨域和覆盖问题_第1张图片
image

代码如下:

  • props中的数据都是父组件传输过来的
  • backImg必须最先draw,因为其他图片要覆盖它,如果它最后才draw,必然会覆盖其他图片
// 邀请卡模板2 -- UI
// 图片自己去照一张可用的
const cardModel2 = require('../statics/images/card_model_2.png');
const CardModel2 = React.createClass({
    propTypes: {
        type: React.PropTypes.string,
        backImg: React.PropTypes.string,
        avatar: React.PropTypes.string,
        nickname: React.PropTypes.string,
        startTime: React.PropTypes.number,
        fileName: React.PropTypes.string,
        title: React.PropTypes.string,
        shareDesc: React.PropTypes.string,
        expireDateTime: React.PropTypes.number
    },
    render: function () {
        return (
            
您的浏览器不支持canvas {/**/} {/**/}
) }, componentDidMount: function () { const _this = this; this.timer = setTimeout(() => { _this.generateImage(); }, 100); }, componentWillUnmount: function () { this.timer && clearTimeout(this.timer); this.imgListener && clearInterval(this.imgListener); }, generateImage: function () { const _this = this; const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext('2d'); let avatarFlag, backImgFlag, codeImgFlag; // 图片加载顺序: 背景图 -> 二维码 -> 用户头像 //添加头像 let avatar = new Image; // avatar.crossOrigin = "anonymous"; avatar.crossOrigin = true; avatar.onload = function () { ctx.drawImage(avatar, 112, 168, 80, 80); avatarFlag = true; _this.canvas2Img(); }; // 二维码 let codeImg = new Image; // codeImg.crossOrigin = "anonymous"; codeImg.crossOrigin = true; codeImg.onload = function () { ctx.drawImage(codeImg, 146, 712, 156, 156); codeImgFlag = true; avatar.src = _this.props.avatar || defaultUserAvatar; }; //添加背景图 let backImg = new Image; backImg.crossOrigin = "anonymous"; backImg.onload = function () { ctx.drawImage(backImg, 0, 0, 750, 1000); backImgFlag = true; codeImg.src = _this.props.fileName; }; backImg.src = cardModel2; // 周期监测 // this.imgListener = setInterval(() => { // if (avatarFlag == true && backImgFlag == true && codeImgFlag == true) { // _this.canvas2Img(); // clearInterval(_this.imgListener); // } // }, 100); }, canvas2Img: function () { const canvas = this.refs.canvas; const ctx = canvas.getContext('2d'); let ts, date; const _this = this; // 姓名 ctx.font = "24px Yahei"; ctx.fillStyle = "#f46a7c"; const nickname = this.props.nickname || ""; ctx.fillText("你的好友 " + nickname, 212, 196); // 提示 ctx.font = "24px Yahei"; ctx.fillStyle = "#f46a7c"; ctx.fillText("我发现好内容 想与你分享", 212, 236); // 课程名称 ctx.font = "36px Yahei"; ctx.fillStyle = "#f8f7f5"; ctx.textAlign = "center"; let courseTitle = this.props.title || ""; if (courseTitle.slice(0, 11)) { ctx.fillText(courseTitle.slice(0, 10), 375, 354); } if (courseTitle.slice(10, 20)) { ctx.fillText(courseTitle.slice(10, 20), 375, 394); } // 课程描述 ctx.font = "26px Yahei"; ctx.fillStyle = "#4ec4ce"; ctx.textAlign = "center"; const shareDesc = this.props.shareDesc; if (shareDesc && shareDesc.length > 0) { ctx.fillText(shareDesc.slice(0, 18), 375, 466); if (shareDesc.slice(18, 36)) { ctx.fillText(shareDesc.slice(18, 36), 375, 498); } if (shareDesc.slice(36, 53)) { ctx.fillText(shareDesc.slice(36, 53) + "...", 375, 540); } } // 开课时间 if (this.props.type == '1' && this.props.startTime) { ts = new Date(this.props.startTime); date = "开课时间 " + (ts.getMonth() + 1) + "月" + ts.getDate() + "日 "; ts = ts.toTimeString().split(":"); date += ts[0] + ":" + ts[1]; ctx.font = "26px Yahei"; ctx.fillStyle = "#f8f7f5"; ctx.textAlign = "center"; ctx.fillText(date, 375, 636); } // 邀请卡到期时间 if (this.props.expireDateTime) { ts = new Date(this.props.expireDateTime); date = "邀请卡到期时间:" + ts.getFullYear() + "年" + (ts.getMonth() + 1) + "月" + ts.getDate() + "日"; ctx.font = "24px Yahei"; ctx.fillStyle = "#285778"; ctx.textAlign = "center"; ctx.fillText(date, 375, 924); } let imgUrl = canvas.toDataURL(); _this.refs.showImg.src = imgUrl; } });

你可能感兴趣的:(canvas上插入图片时跨域和覆盖问题)