九宫格心形拼图

九宫格心形拼图

这是一个微信小程序,用来生成九宫格心形的图片。html

连接: https://pan.baidu.com/s/1sPx6FJlqzlFZ0Md6xy9jzw 提取码: 88v8git

扫码体验github

微信小程序须要的代码,在 src 文件夹中。canvas

说明

前几天在朋友圈看到好几回这种图片。小程序

这里写图片描述

这种图片,是用九张图片拼成的一个心形。微信小程序

感受颇有趣,就上网查了查怎么作,大部分的说法就是用美图秀秀的拼图功能来作, 在微信小程序中也有专门作心形拼图的小程序,我都试了试以后,感受还能够更加简单一些,因而我就本身作了个小程序。api

实现小程序的思路

一、有两个 canvas,一个小的 canvas 显示最后会是什么样子,一个大的 canvas 用来最后进行截图,生成图片,保存到相册。
经过CSS的定位,把大的 canvas 移到屏幕外面不让用户看到就能够了。
而若是用小的canvas 保存图片的话,最后的图片有些模糊。数组

二、canvas 能够当作一个 9 * 9 的网格,微信

这里写图片描述

用一个叫 heart 的数组来表示就是这样的。优化

这里写图片描述

用其中的小格子,来拼出心形,根据数组的内容在 canvas 上进行渲染。

小程序的功能

这个小程序有 选择单张图片,选择多张图片,补充图片,保存图片,重置,推荐,意见反馈,这几个功能。

选择单张图片

当用户点击心形区域的时候,就能够选择单张图片,调用 wx.chooseImage 就能够从本地相册选择图片,而后就把这张图,画在 canvas上,具体画的位置就是用户点击的位置。

在小的 canvas上绑定 touchend 事件,触发事件后,事件中有一个 changedTouches 属性,这是一个保存了,当前变化的触摸点信息的数组,这个数组中的元素有 x 和 y 属性,也就是触摸点距离 canvas 左上角的距离。

// 触摸点在 x 轴的值
var x = e.changedTouches[0].x;
// 触摸点在 y 轴的值
var y = e.changedTouches[0].y;

有 x 轴 和 y 轴的距离后,算出具体应该画在哪一个格子上。

//grid 表示一个格子的宽度

// 肯定 x 轴是在第几个格子
x = Math.floor(x / grid);

// 肯定 y 轴是在第几个格子
y = Math.floor(y / grid);

知道在哪一个格子画以后,就要肯定画图片的哪部分了,由于全部的格子都是正方形的,可是用户选择的图片不必定是正方形,若是压缩成正方形会很难看,因此我画的时候,选择了正中间的部分来画,

经过 wx.getImageInfo 来获取图片信息,以短边为正方形的宽,而后从(长边 - 短边)/2 的地方来画。

// 获取图片的宽和高
var width = res.width;
var height = res.height;

//  若是图片不是正方形,只画中间的部分
// sWidth 表示正方形的宽
var sWidth = width > height ? height : width;
// sx 是源图像的矩形选择框的左上角 X 坐标
var sx = 0;
// sy 是源图像的矩形选择框的左上角 y 坐标
var sy = 0;
if (width > height) {
	sx = (width - height) / 2;
}
if (width < height) {
	sy = (height - width) / 2;
}

知道画什么,在哪里画以后,调用 canvasContext.drawImage 来画就能够了。

选择多张图片

选择多张图片,一样是调用 wx.chooseImage 方法,成功选择多张图片后,返回的对象中有一个 tempFilePaths 属性,这个属性保存了,图片的本地文件路径列表。

这里写图片描述

而后遍历 heart 数组,也就是保存心形数据的数组,若是数组中某个元素的值是1,也就是说在心形范围内,就按顺序从 tempFilePaths 中取一张图片画上去,画的时候一样的,若是不是正方形就只画中间的部分。

补充图片

在 image 的文件中,有保存几张图片,用来补充心形,他们的路径保存在一个数组中。

// 用来补充心形的图片
 images: [
   '../../images/1.jpg',
   '../../images/2.jpg',
   '../../images/3.jpg',
   '../../images/4.jpg',
   '../../images/5.jpg',
   '../../images/6.jpg',
   '../../images/7.jpg',
   '../../images/8.jpg',
   '../../images/9.jpg',
   '../../images/10.jpg',
 ]

而后就是遍历 heart 数组,若是数组的某个元素的值是1,就随机从这组图片中选择一张画上去。

画一张图片,画多张图片,补充图片,他们都是在 canvas 上画图片,为了不已经画了图片的位置被覆盖,他们所画的图片的等级是不一样的。

补充图片:1
画多张图片:2
画一张图片:3

等级高的能够覆盖等级低的,等级低的不能覆盖等级高的,同等级的,除了画多张图片的不能覆盖,其他的两种状况,均可以覆盖。

简单意思就是: 补充图片,补充完了以后,再补充会把原来补充的覆盖掉,可是用户选择的图片不会被覆盖掉。
画多张图片,能够覆盖掉补充的图片,但用户选择的图片也不会覆盖掉。
画一张图片,无论这个位置有没有图片,都会再画一张。

保存图片

保存图片的时候,就是按顺序对大的 canvas 进行截取,而后保存成图片,主要靠 wx.canvasToTempFilePath 这个API来实现,这个 API ,能够把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。

这里要注意几个细节

一、为了不最后保存的图片有黑色背景,最好开始的时候就在 canvas 上画一个 和 canvas 大小同样的矩形,矩形填充上颜色。

二、为了保存的图片,在用户的相册中也能保持心形。须要按下面这个顺序来保存图片

这里写图片描述

三、wx.canvasToTempFilePath 中有两个选填的参数 destWidth 和 destHeight,这个两个参数决定 输出图片宽度和高度,若是不是准确的知道是多少,用默认值就能够。

destWidth 和 destHeight 单位是物理像素(pixel),canvas 绘制的时候用的是逻辑像素(物理像素=逻辑像素 * density),因此这里若是只是使用 canvas 中的 width 和 height(逻辑像素)做为输出图片的长宽的话,生成的图片 width 和 height 其实是缩放了到 canvas 的 1 / density 大小了,因此就显得比较模糊了。

而默认值是 width * 屏幕像素密度

这里写图片描述

文档中提到的屏幕像素密度,应该不是指每英寸屏幕所拥有的像素数,而是指设备像素比(pixelRatio),也就是用多少个物理像素去显示 1px 的 CSS 像素。 用API wx.getSystemInfo 能够查看设备像素比

wx.getSystemInfo({
  success: function(res) {
    console.log(res.pixelRatio)
  }
})

这里若是个人理解有误,还请知道的小伙伴指出。

说了这么多,主要就是想说用默认的值其实就已经很清晰了。

四、由于要保存9张图片,因此须要一些时间,这个时候就须要一个进度条了,保存图片的时候,显示进度条,禁用保存按钮,毕竟点击一下按钮就是9张图片,因此这个时候仍是禁用了好,每保存一张图片进度条的值就 +12 ,超过100的时候,就表示 9张图片都保存好了。

而微信小程序中也恰好有进度条(progress)这个组件

重置

这个功能就是遍历 heart 数组,用一种颜色,根据数组内容,把心形画出来。而后再在 x 轴 和 y 轴上画两条线,行成九宫格的样子。

推荐 和 意见反馈

<button open-type='share'>推荐给朋友</button>
 <button open-type='feedback'>意见反馈

这个两个功能就是用了,微信小程序的 button 组件,这里须要注意的就是,在清除 button 的默认样式时,须要把 button 的 after 伪元素的边框也去掉。

button::after{
  border: 0; 
}

能够优化的地方

有一些地方是小程序在替用户作选择,好比,若是所选择的图片不是正方形,就画中间的部分,可是中间的部分不必定是用户想要的,而若是每张图片都要用户本身来选择画哪部分,显然是有些麻烦了,这里还能够继续优化下。

还有在补充图片的时候,补充的图片也不必定是用户喜欢的,因此这部分再考虑是否是能够加一些标签,用户选择不一样的标签,来补充符合标签的图片,相似 QQ音乐的歌词海报这样。

这里写图片描述

总结

此次作的这个九宫格心形拼图的小程序,初版已经上线了。

这个小程序无论在代码,仍是功能上都还有许多地方能够继续优化,若是有须要的朋友能够直接拿去改。

若是你喜欢这个小程序的话,能够 star 支持一下。

目前,这个小程序有进行一些优化,具体能够点这里

若是须要最开始的版本,请到这里

相关文章
相关标签/搜索