美文网首页
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