失败的 canvas 实验

  一到冬天窝在被窝里就想整点代码玩,凌晨 4 点多睡醒一边撸猫一边在 B 站搜了一下 canvas 教程,一个创建画布 + 调整画布尺寸的教学花了我整整 15 分钟,这还是在我全程 1.5 倍速最后实在忍无可忍调到 2 倍速的情况下。
  这种代码教学一定要开个文本框一边说话一边手打讲义还疯狂错字漏字用键盘调整光标的惯例到底是谁发明的?不需要的鼠标可以捐了吗?打字慢就不能提前准备好讲义吗?而且你打字速度都已经这么慢了选字的时候就不能用你那 800 度的老年光学捕捉设备仔细识别一下?还是说你只有在敲空格的时候才能感觉到打字的快感???
  吐槽完才发现这是个网课录屏视频。好吧,要混时长骗钱的嘛,是不是等我学成了以后也能这么去骗人钱了?
  想想还是算了,毕竟我打字太快……


.+†+.

  最后实在没耐心继续看那个破视频了,反正我只是想做个捏人系统来着【

  • 谷歌 psd 2 canvas,并没有人造这个轮子,倒是查到 flash CC 可以导出 canvas 对象,但是我又不做动画,而且苏菲狗也跑不动你……
  • 谷歌 canvas 图层,结果是 canvas 内部并不能实现图层,需要靠多个 canvas 画布叠在一起实现【好菜啊 :-cmx-02-:
  • 谷歌 canvas 导入位图,和 css 一样加个链接就可以了。

  所以我好像明白为啥没人造这个轮子了……好像确实造不出来也没什么必要,反正都是一层一层地导图进去 OTL
  于是以下是个 canvas 练习,用的还是之前画的像素小光头,我也不知道我还能不能记得按钮的 JS 怎么写 emmmmmmm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<escape>

<div class='game-box'>
<canvas id='g-body' width=120px height=134px></canvas>
<canvas id='g-eye' width=120px height=134px></canvas>
</div>

<script type="text/javascript">
var geye = document.getElementById('g-eye');
var ctxeye = geye.getContext('2d');
var eyeImg = new Image();
eyeImg.src = '191217-canvas/img/eye-01.png';
eyeImg.onload = function () {
alert('?');
ctxeye.drawImage(this, 0, 0);
alert('???')
}

</script>

</escape>

  好烦啊练习失败了……
  我设置了图片加载完弹一个 alert,绘制完再弹一个 alert,结果两个 alert 连着弹,弹完别说 canvas 了,整个 post-body 都没加载出来……你妈的为什么啊……
  最后决定还是用 div 和 CSS 背景图实现吧,虽然不能导出图片,但是反正我也只是想自己做个捏证件照的系统而已,导不出不是更好了嘛【

  新建了一个页面并加上 layout: false 之后成功渲染出来了,【点我】
  果然是正文内的 canvas 加载顺序和渲染器有冲突,那就不是我的问题嘛【
  而且一个很迷惑的事情,我查到的所有资料都告诉我 canvas 容器不能分图层要创建多个容器,但是 picrew 的网页上又确确实实是只有一个 canvas 的,这是为什么啊【

  马个参考资料:

需要的功能

  • 类似 picrew 的捏人小游戏 ✓
  • 为了方便导出所以所有内容都要画在同一个 canvas 画布里 ✓
  • 分为 body,eye,hair 等等不同的部件,每个部件下又有不同的样式选择,需要在变换部件的同时保证堆叠次序不变 ✓
    • 我查到的资料告诉我只能从最底下开始一层一层重画
    • 我觉得这一条用空 div 的背景图来实现比 canvas 简单多了啊可恶!
  • 打开页面时所有部件都是随机样式 ✓
  • 点击【随机按钮】也可以将所有部件重置为随机样式 ✓
  • 部件选择按钮与颜色选择按钮是分开的,需要获取两个数据后再绘制正确的图片 〇【我确定这个功能我以前写过但是我 tm 忘记我怎么写的了为什么我之前的代码没有写注释呢呜呜呜呜呜不对啊你 tm 之前写的是 svg 直接上色了并没有选择图片好吗!
  • 点击【导出】按钮可以保存 png 图片到本地,并且自动重命名 〇【这个应该有现成的代码可以照抄吧……

代码设计

  再顺便马个代码逻辑,怕我以后又忘了……

  • 1. 定义:
    • bodyList = [body url 1, body url 2, ...【图片 url 列表]
    • eyeList = [eye url 1, ...【也是图片列表]
    • 依次类推定义完全部图片列表
  • 2. 赋值默认显示的图片,设定一个随机值
    • bodyImg = bodyList[?]
    • 以此类推【随机数怎么选取我还不会写 x
  • 3. 定义:function drawCanvas {
    • 绘制背景;
    • 绘制 bodyImg;
    • 绘制 eyeImg;
    • 以此类推从底层到顶层重绘整个画面【大概还要在前面加上清空画布,在最后加上保存?
    • }
  • 4. 按钮动作:
    • 按下【body x】按钮时
      • bodyImg 赋值为 bodyList [x];
      • 并执行 drawCanvas
    • 按下【eye x】按钮时
      • eyeImg 赋值为 eyeList [x];
      • 并执行 drawCanvas
    • 以此类推
  • 5. 随机按钮
    • 按下随机按钮时
      • bodyImg 赋值为 bodyList[?]【随机数,
      • eyeImg 赋值为 eyeList[?];
      • ...【以此类推赋值全部 xxImg 属性为随机数
      • 执行 drawCanvas

可能存在的问题

  • 随机按钮的功能与默认显示的图片重复,是否能合并?
    • 解决方案:定义 function randomImg {
      • 执行原第五步内容
    • }
    • 删去 2.,将 randomImg 的定义移到 3. 和 4. 中间
    • 在页面加载完成后执行 randomImg
    • ……解决个锤子啊放到 3. 后面执行的时候会报错 drawCanvas 未定义的好吗!!!
    • 那就在 randomImg 中删掉【执行 drawCanvas】,定义 function allRandom {
      • 执行 randomImg;
      • 执行 drawCanvas
    • }
    • 在页面加载完成后执行 allRandom
    • 在点击随机按钮后也执行 allRandom
    • 这样大概就真的解决了?
  • 在 canvas 中绘制图片需要等待图片列表加载完成,这个等待加载如何检测?
  • 图片数量过大的情况下是先一次性加载完全部图片,还是直接动态加载需要绘制的图片?
  • 如果一次性加载是否需要添加 loading 动画?
  • 动态加载又要怎么写啊 (╯°Д°)╯︵┴┴
    • 解决方案:在每一层绘制前加入 newImgxxImg.onload
    • 大概就是动态加载了吧……大概……
  • 赋值的随机数不能超过数组长度,这个条件限制是能一行搞定还是要每个数组都来一条……
  • 为了减少图片上传数量,是否要将每个部件的图片合并为同一张,然后在 canvas 绘制时进行截取?

颜色按钮设计

  构思一下大概的颜色按钮设计?希望能做出来一个通用的颜色按钮……至少发型部分要通用,毕竟我画了 6 层头发【
  思路不是很清晰,写出来大概只有我自己看得懂,主要是怕忘了 OTL

  • 将发型样式 hairStyle 编号为 01234,颜色 hairColor 编号为 ABCDE,图片文件命名为 hair-0A,其它部件以此类推,假设调色盘都是公用的 ABCDE
  • 点击【发型样式 0】按钮后赋值 hairStyle = 0,点击【颜色 A】按钮后赋值 hairColor = A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var hairImg = newImage(),
eyeImg = newImage(),
...;

function drawCanvas () {
var 【cvx 画布】 = document.getElementById('canvas');
var ctxCanvas = 【cvx 画布】.getContext('2d');
【背景及其它层】
hairImg.src = '`$hairSrc';
hairImg.onload = function () {
ctxCanvas.drawImage(this, 0, 0);
}
}

function changeHair (hairStyle) {
var hairSrc = 'hair-' + hairStyle + hairColor + .png;
drawCanvas;
}
function changeColor (hairColor) {
var hairSrc = 'hair-' + hairStyle + hairColor + .png;
drawCanvas;
}

【发型样式 0】.onclick = function changeHair (0)
【颜色 A】.onclick = function changeColor (A)

  又搜了一下发现同时绘制多张图片似乎并不能这么写……
  但是我网页里用的 window.onload 成功了,那还是要等全部加载完再开始画吗 OTL
  还是马参考资料: