美文网首页
canvas上插入图片时跨域和覆盖问题

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

作者: 吴博 | 来源:发表于2017-05-26 21:47 被阅读0次

终于搞定了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转化为的图片的预览图:

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 (
            <div>
                <canvas id="myCanvas" ref="canvas" width="750" height="1000">您的浏览器不支持canvas</canvas>
                {/*<img src={cardModel2} ref="backImg" style={{display: 'none'}} crossOrigin="anonymous"/>*/}
                {/*<img src={this.props.avatar} ref="avatar" style={{display: 'none'}} crossOrigin="anonymous"/>*/}
                <img src={this.props.fileName} ref="fileName" style={{display: 'none'}} crossOrigin="anonymous"/>
                <img ref="showImg" className="showImg" crossOrigin="anonymous"/>
            </div>
        )
    },
    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上插入图片时跨域和覆盖问题

      本文链接:https://www.haomeiwen.com/subject/iutffxtx.html