ホームページ >ウェブフロントエンド >H5 チュートリアル >Canvasを使った9マスのハート型パズルの実装方法(コード付き)

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

不言
不言オリジナル
2018-08-01 13:59:574956ブラウズ

この記事では、キャンバスで9つの正方形のハート型のパズルを実現する方法を紹介します。これは、必要な友人に参考になると思います。

説明

数日前、モーメントでこのような写真を何度か見ました。

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

このような絵は9枚の絵で作られたハートの形です。

とても興味深いと思ったので、その方法をオンラインで調べました。ほとんどの提案は、Meitu Xiu Xiu のパズル機能を使用して行うというものでした。WeChat ミニ プログラムには、次のようなミニ プログラムもあります。ハート型のパズルを作ることに特化しています。その後、すべて試してみて、もっと簡単なプログラムを自分で作成しました。

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

小さなプログラムを実装するというアイデア

1. 2 つのキャンバスがあり、小さなキャンバスは最終的にどのようになるかを示し、大きなキャンバスはスクリーンショットを撮ったり、写真を生成したりするために使用されます。をクリックしてアルバムに保存します。
CSS の位​​置調整により、大きなキャンバスを画面の外に移動して、ユーザーに見えないようにするだけです。
また、小さなキャンバスを使用して画像を保存すると、最終的な画像は少しぼやけてしまいます。

2. Canvasは9*9のグリッドとみなすことができ、

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

はheartと呼ばれる配列で表されます。

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

小さなグリッドを使用してハートの形を描き、配列の内容に基づいてキャンバス上にレンダリングします。

ミニプログラムの機能

このミニプログラムには、単一の写真の選択、複数の写真の選択、写真の補足、写真の保存、リセット、推奨、フィードバックの提供といういくつかの機能があります。

単一の画像を選択します

ユーザーがハート型の領域をクリックすると、単一の画像を選択し、wx.chooseImage を呼び出してローカル アルバムから画像を選択し、キャンバス上に画像を描画できます。ユーザーがクリックした場所です。

小さなキャンバスに touchend イベントをバインドします。イベントがトリガーされた後、イベントには、現在変更されているタッチ ポイント情報を保存する配列があります。この配列の要素には、x 属性と y 属性があります。タッチポイントとキャンバスの左上隅の間の距離も同様です。

// 触摸点在 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 <p>何をどこに描画するかがわかったら、canvasContext.drawImage を呼び出して描画するだけです。 </p><h4>複数の画像を選択する</h4><p> 複数の画像を選択するには、wx.chooseImage メソッドも呼び出されます。返されるオブジェクトには、画像のローカル ファイル パス リストが保存されます。 </p><p><span class="img-wrap"><img src="https://img.php.cn//upload/image/676/859/705/1533102912371640.png" title="1533102912371640.png" alt="Canvasを使った9マスのハート型パズルの実装方法(コード付き)"></span></p><p> 次に、ハート型のデータを格納する配列であるハート型の配列を走査します。配列内の要素の値が 1 の場合、つまりハート型の範囲内にある場合は、 tempFilePaths から画像を順番に描画します。正方形でない場合は、中央部分だけを描画します。 </p><h4>補足画像</h4><p> 画像ファイルには、ハートの形を補足するためにいくつかの画像が保存されており、それらのパスが配列に保存されています。 </p><pre class="brush:php;toolbar:false"> // 用来补充心形的图片
 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',
 ]

次に、ハート配列を走査し、配列の要素の値が 1 の場合、この絵のセットから絵をランダムに選択します。

絵を描く、複数の絵を描く、絵を補足するなど、描いた絵の位置が上書きされないように、それぞれ絵のレベルが異なります。

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

レベルが高い人はレベルが低い人をカバーできますが、レベルが低い人はレベルが高い人をカバーすることはできません。複数の絵を描く場合を除き、どちらの場合も可能です。

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

保存图片

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

这里要注意几个细节

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

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

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

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

destWidthdestHeight 单位是物理像素(pixel),canvas 绘制的时候用的是逻辑像素(物理像素=逻辑像素 * density),所以这里如果只是使用 canvas 中的 width 和 height(逻辑像素)作为输出图片的长宽的话,生成的图片 width 和 height 实际上是缩放了到 canvas 的 1 / density 大小了,所以就显得比较模糊了。

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

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

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

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

这里如果我的理解有误,还请知道的小伙伴指出。

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

4、因为要保存9张图片,所以需要一些时间,这个时候就需要一个进度条了,保存图片的时候,显示进度条,禁用保存按钮,毕竟点击一下按钮就是9张图片,所以这个时候还是禁用了好,每保存一张图片进度条的值就 +12 ,超过100的时候,就表示 9张图片都保存好了。

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

重置

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

推荐 和 意见反馈

 <button>推荐给朋友</button>
 <button>意见反馈</button>

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

button::after{
  border: 0; 
}

可以优化的地方

有一些地方是小程序在替用户做选择,比如,如果所选择的图片不是正方形,就画中间的部分,但是中间的部分不一定是用户想要的,而如果每张图片都要用户自己来选择画哪部分,一共81张图片,显然是有些麻烦了,这里还可以继续优化下。

还有在补充图片的时候,补充的图片也不一定是用户喜欢的,所以这部分再考虑是不是可以加一些标签,用户选择不同的标签,来补充符合标签的图片,类似 QQ音乐的歌词海报这样。

Canvasを使った9マスのハート型パズルの実装方法(コード付き)

总结

这次做的这个九宫格心形拼图的小程序,第一版已经上线了。

开源地址:https://github.com/FEWY/jigsaw  

相关文章推荐:
HTML5 Canvas实现交互式地铁线路图

使用h5 canvas实现时钟的动态效果

以上がCanvasを使った9マスのハート型パズルの実装方法(コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。