我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛
中秋就快到了,一般月饼上都会刻有文字或者图案,那假如你收到的月饼上,刻有你专属的名字,是不是很惊喜?接下来就让我们用canvas来实现刻有专属于你的月饼吧!!!
先看几张效果图
实现原理
实现原理非常简单,除了生产日期及月饼中的文字,其他部分是一张背景图。我们要做的就是将文字信息填充到月饼中间即可。
代码实现
代码实现后的页面效果:
首先我们页面有个输入框,输入文字,点击确定时将文字信息渲染到canvas中。同时还有一个点击下载保存的按钮。为了排版美观,限制只能输入1,2,4个文字。
相关代码
html:
<canvas id="myCanvas" width="400" height="300" style="border:1px solid #d3d3d3;"></canvas>
<input placeholder="点击输入内容,为排版美观,只能输入1/2/4个文字" id="input" maxlength="4" style="width: 300px" />
<button>确定</button>
<button id='download'>下载</button>
复制代码
js:
var input = document.querySelector('#input')
var downloadBtn = document.querySelector('#download')
input.addEventListener('change', (e) => {
processText(e.target.value)
})
var canvas = document.getElementById("myCanvas")
var ctx = canvas.getContext("2d")
downloadBtn.addEventListener('click', saveImg)
var img = new Image()
img.src = 'https://juejin.cn/post/images/mooncake.png'
// 字体大小,根据输入的文字数量调整
var fontSize = 36
img.onload = function () {
drawBackground()
processText()
}
var date = new Date()
var [y, m, d] = [date.getFullYear(), date.getMonth() + 1, date.getDate()]
var dateStr = `${y}/${m < 10 ? '0' + m : m}/${d < 10 ? '0' + d : d}`
function _fixType(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
function processText(text = '花好月圆') {
var textNum = text.length
if (![1, 2, 4].includes(textNum)) {
return alert('为排版美观,只能输入1/2/4个文字!')
}
switch (textNum) {
case 1:
fontSize = 68
var textY = canvas.height / 2 + 24
draw(text, textY)
break
case 2:
fontSize = 42
var textY = canvas.height / 2 + 14
draw(text, textY)
break
default:
fontSize = 32
var textY = canvas.height / 2 - 6
draw(text.substring(0, 2), textY)
var textY2 = canvas.height / 2 + 30
drawText(text.substring(2, 4), textY2)
}
}
function draw(text = '花好月圆', textY) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawBackground()
drawText(text, textY)
drawDate()
}
// 绘制生成日期
function drawDate() {
ctx.fillStyle = '#000'
ctx.font = '14px KaiTi'
ctx.fillText(dateStr, 200, 58)
}
// 绘制背景
function drawBackground() {
ctx.drawImage(img, 0, 0, 400, 300)
}
// 绘制文字
function drawText(text, textY) {
ctx.font = `${fontSize}px KaiTi`
var textWidth = ctx.measureText(text).width
ctx.strokeStyle = '#bf814b'
ctx.shadowOffsetX = 1
ctx.shadowOffsety = 1
ctx.shadowColor = '#000'
ctx.shadowBlur = 2
ctx.strokeText(text, 200 - textWidth / 2, textY);
ctx.shadowOffsetX = -1
ctx.shadowOffsety = -1
ctx.shadowColor = '#e0b64c'
ctx.shadowBlur = 1
ctx.fillStyle = '#bf814b'
ctx.fillText(text, 200 - textWidth / 2, textY);
}
// 图片保存本地
function saveImg() {
var canvas = document.getElementById("myCanvas")
var image = new Image();
var imgData = canvas.toDataURL({ format: 'image/png', quality: 1, width: 800, height: 600 });
var url = imgData.replace(_fixType('png'), 'image/octet-stream');
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = imgData;
save_link.download = 'mooncake.png';
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
}
复制代码
以上就是完整的js逻辑实现,代码量不多应该还是比较容易阅读理解。
这里值得一提的是,我们要如何实现月饼中的文字凸显的3D效果?css中我们可以用text-shadow属性实现,而canvas当中其实有对应的api可以实现:
- shadowOffsetX :横向偏移量
- shadowOffsetY :纵向偏移量
- shadowBlur :模糊范围
- shadowColor :阴影颜色
详细实现可以查看drawText
方法,另外要重点要提及的是,要达到文字凸显3D效果,文字颜色跟背景色必须一样,阴影颜色则可以细调。
注意
如果你是在浏览器中直接打开html代码,点击下载按钮时会遇到报错
我们要用请求的方式打开才可以,方法也非常简单。vs code 搜索安装Live Server插件,点击leve server开启服务访问即可。
相关参考资料
月饼素材图见文章底部评论
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END