美文网首页
[项目总结]用canvas画个卡片

[项目总结]用canvas画个卡片

作者: 漫溯 | 来源:发表于2018-05-21 20:37 被阅读0次

动用canvas来画图片是因为有一些场景里存在着需要动态改变的东西,比如说随机取出一句话写到卡片上,或者根据当前日期动态改变登机牌等等。

ticket.png

设置画布背景

如果直接按照画布的大小来绘制图片的话会导致图片模糊,这是由于retina屏幕的原因,此时可以根据当前屏幕的设备像素比devicePixelRatio来改变画布的大小。
以iPhone6来说,屏幕像素比是2,那么就可以画一个两倍大小的画布。
当然,一般设计师给我们的设计稿都是两倍实际大小,所以一种取巧的办法是把画布的长宽设置为图片的长宽,样式上在使元素自适应屏幕就好了。

图片是一张张画上去的,后面的图片会覆盖掉前面的图片,因此一定得安排好每张图的加载顺序

imgBg.onload = () => {
    canvas.setAttribute('width', img.width)
    canvas.setAttribute('height', img.height)
    ctx.drawImage(imgBg, 0, 0, imgBg.width, imgBg.height)

    imgAvatar.onload = () => {
        ctx.drawImage(imgAvatar, 370, 380, imgAvatar.width, imgAvatar.height)
        self.drawText(ctx)
        self.createImg(cavas)
    }
    imgAvatar.src = `/url/avatar.png?t=05093`
}
imgBg.src = `/url/bg.jpg`

这是简单的只有两张图的情况,如果更多的话可以考虑把所有画图任务都保存在一个队列中,每次一张图load并执行后从队列中取出下一次需要画图的任务。

绘制文字

画完背景图了,怎么也得写几行文字。在处理多行文字中,可以将文字存于数组中,每写完一行移动画布坐标,写下一行。
如果有特殊的需求,比如针对名字做特殊的样式处理,可以保存画布状态后面再restore来记住之前使用的样式。
同一行文字改变了样式所占用的空间宽度也不同,这里有个比较好用的方法measureText
ctx.measureText(strA).width
测量了特殊处理的文字宽度可以方便知道下一次的绘制的应该移动多大的距离

// 类似的一句话,把xxx替换为用户的昵称
function drawText(ctx) {
    let msgArr = ['对于xxx来说,balabala', '星座balabalabala']
    for(let i = 0, len = msgArr.length; i < len; i++) {
        ctx.translate(0, 40)
        if (msgArr[i].indexOf('xxx') !== -1) {
            let strA = msgArr[i].split('xxx')[0]
            let strB = msgArr[i].split('xxx')[1]
            ctx.save()
            if (strA) {
                let textLen = ctx.measureText(strA).width
                ctx.fillText(strA, 0, 20)
                ctx.translate(textLen, 0)
            }
            // 名字做特殊处理
            ctx.save()
            ctx.font = "42px Aril"
            ctx.fillStyle = '#c85d8a'
            let nick = this.nickName ? this.nickName : 'TA'
            ctx.fillText(nick, 0, 20)
            let nameLen = ctx.measureText(nick).width
            ctx.restore()

            ctx.translate(nameLen, 20)
            ctx.fillText(strB, 0, 0)
            ctx.restore()
        } else {
            ctx.fillText(msgTopArr[i], 0, 20)
        }
    }
}

把画布转换为图片

使用canvas的toDataURL方法转为base64格式,放到页面中一个imgsrc属性中就完成了。
这里可以根据自己页面设计,我是将图片设置为透明覆盖到了画布上,可以方便长按保存。

createImg(canvas) {
    let imgData = canvas.toDataURL('image/jpg')
    this.$refs['pic-shadow'].src = imgData
}

canvas图片跨域问题

canvas限制图片资源不能跨域,这里用的两种解决方式

  1. 如果图片资源服务器支持跨域访问,在创建img时候加一句img.crossOrigin = "Anonymous"就可以避免跨域问题。
  2. 如果不能去改服务器头部的话,而且其实用到的图片不是特别多,可以把图片转成base64格式保存在一个js的文件中,直接拿来用就可以了。

模拟长按

layer.png

在微信里面对img图片长按保存是没有问题的,但在Android版的自家APP中就不灵了。所以这里根据环境判断是否显示mask层,通过模拟长按来调出自定义的下载菜单,再使用bridge方法完成下载。

用到了touch的3个事件,对目标元素的touchstart、 touchmovetouchend分别绑定对应的函数,500毫秒后再调用下载方法,实现对长按模拟。

let timer = null
function touchStart() {
  timer = setTimeout(savePhoto, 500)
}
function touchMove() {
  clearTimeout(timer)
}
function touchEnd() {
  clearTimeout(timer)
}
function savePhoto() {
  // some bridge methods
}

相关文章

  • [项目总结]用canvas画个卡片

    动用canvas来画图片是因为有一些场景里存在着需要动态改变的东西,比如说随机取出一句话写到卡片上,或者根据当前日...

  • Android Canvas小案例粒子爆炸效果

    概述 本文承接Android Canvas总结下述小案例仅为Canvas的api的试用总结,非项目使用demo!!...

  • Android Canvas 小案例组合动画

    概述 本文承接Android Canvas总结下述小案例仅为Canvas的api的使用总结,非项目使用demo!!...

  • 近期工作总结 8.12

    又是久违的总结。最近在做的项目是一个动画,用 Canvas 实现,用的库是 Pixi,做一个射击抽奖小游戏。做动画...

  • 用Canvas画个圆盘

    需求的来源通常是工作,这次要完成功能核心是一个向量图,嗯...其实就是一个定制化的仪表盘,换做平时一个上午就能搞定...

  • HTML5中canvas使用

    1、Canvas基础 2、Canvas画直线 3、Canvas画矩形 4、Canvas画文字 5、Canvas画圆...

  • 用canvas画虚线

    今天的任务是用canvas画小时候练字用的田字格,一般的田字格是虚线。事先知道canvas里有setLineDas...

  • canvas开发项目总结

    canvas绘图 对canvas设置宽高,只能通过属性设置。使用css设置宽高会让canvas变形 开发手机端页面...

  • vue-html2canvas插件

    移动端项目需要生成海报,找了挺久的插件,还是选择了html2canvas,不用画canvas,直接写html生成c...

  • Promise的一次实际使用

    最近项目中有一个用canvas画拓扑图的需求,实际开发中的遇到的一个问题是我需要等三张资源图片加载完再去绘制,否则...

网友评论

      本文标题:[项目总结]用canvas画个卡片

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