微信小程序微信小程序canvas拖拽、截图组件功能拖拽、截图组件功能
主要介绍了微信小程序canvas拖拽、截图组件功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
先看下微信小程序先看下微信小程序canvas拖拽功能拖拽功能
组件地址组件地址
github.com/jasondu/wx-… readme近期补上
实现效果实现效果
如何实现如何实现
1. 使用canvas
2. 使用movable-view标签
由于movable-view无法实现旋转,所以选择使用canvas
需要解决的问题需要解决的问题
如何将多个元素渲染到canvas上
如何知道手指在元素上、如果多个元素重叠如何知道哪个元素在最上层
如何实现拖拽元素
如何缩放、旋转、删除元素
看起来挺简单的嘛,就把上面这几个问题解决了,就可以实现功能了;接下来我们一一解决。
如何将多个元素渲染到如何将多个元素渲染到canvas上上
定义一个DragGraph类,传入元素的各种属性(坐标、尺寸…)实例化后推入一个 渲染数组 里,然后再循环这个数组调用实例中的渲染方法,这样就可以把多个元素渲染到canvas上了。
如何知道手指在元素上、如果多个元素重叠如何知道哪个元素在最上层如何知道手指在元素上、如果多个元素重叠如何知道哪个元素在最上层
在DragGraph类中定义了判断点击位置的方法,我们在canvas上绑定touchstart事件,将手指的坐标传入上面的方法,我们就可以知道手指是点击到元素本身,还是删除图标或者变换大小的图标上了,这
个方法具体怎么判断后面会讲解。
通过循环 渲染数组 判断是非点击到哪个元素到,如果点击中了多个元素,也就是多个元素重叠,那第一个元素就是最上层的元素啦。
###如何实现拖拽元素如何实现拖拽元素
通过上面我们可以判断手指是否在元素上,当touchstart事件触发时我们记录当前的手指坐标,当touchmove事件触发时,我们也知道这时的坐标,两个坐标取差值,就可以得出元素位移的距离啦,修改
这个元素实例的x和y,再重新循环渲染 渲染数组 就可以实现拖拽的功能。
如何缩放、旋转、删除元素如何缩放、旋转、删除元素
这一步相对比较难一点,我会通过示意图跟大家讲解。
我们先讲缩放和旋转我们先讲缩放和旋转
通过touchstart和touchmove我们可以获得旋转前的旋转后的坐标,图中的线A为元素的中点和旋转前点的连线;线B为元素中点和旋转后点的连线;我们只需要求A和B两条线的夹角就可以知道元素旋转
的角度。缩放尺寸为A和B两条线长度之差。
计算旋转角度的代码如下:
const centerX = (this.x + this.w) / 2; // 中点坐标
const centerY = (this.y + this.h) / 2; // 中点坐标
const diffXBefore = px - centerX; // 旋转前坐标
const diffYBefore = py - centerY; // 旋转前坐标
const diffXAfter = x - centerX; // 旋转后坐标
const diffYAfter = y - centerY; // 旋转后坐标
const angleBefore = Math.atan2(diffYBefore, diffXBefore) / Math.PI * 180;
const angleAfter = Math.atan2(diffYAfter, diffXAfter) / Math.PI * 180;
// 旋转的角度
this.rotate = currentGraph.rotate + angleAfter - angleBefore;
计算缩放尺寸的代码如下:
// 放大 或 缩小
this.x = currentGraph.x - (x - px);
this.y = currentGraph.y - (x - px);
下面介绍下小程序下面介绍下小程序canvas截图组件截图组件
最近做一个小程序的过程中,需要用到截图功能,网上搜了一下,发现没有符合要求的,就自己搞了个组件,方便复用。
目前功能很简单,传入宽高和图片路径即可,宽高是为了计算截图的比例,只支持缩放和移动。
实现思路是:实现思路是:
1.模拟一个截取框;
2.移动图片位置,缩放图片;
3.获取图片在其中的位置(left,top,width,height);
4.使用canvas绘制图片,然后截取就ok了。
其中第二步的缩放图片比较麻烦,缩放中心点以及平滑缩放
以下是我的实现方式
wxml:
<!--component/picPro/picPro.wxml-->
<scroll-view class='body' hidden="{{hidden}}">
<view class='flex-column flex-between full-height full-width' bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend">
<view class='bg_dark out_item'></view>
<view class='flex-row main flex-between' style='height:{{(windowWidth - margin.left - margin.right)/ratio + "px"}}'>
<view class='bg_dark main_item full-height' style='width:{{margin.left + "px"}}'></view>
<view class='inner relative full-width' id='showArea'>
<image class='absolute img' src='{{src}}' style="width:{{img.width}}px;height:{{img.height}}px;left:{{img.left}}px;top:{{img.top}}px;"></image>
<canvas canvas-id='imgCanvas' class='absolute img_canvas full-height full-width' />
<view class='absolute inner_item left_top'></view>
<view class='absolute inner_item right_top'></view>
<view class='absolute inner_item right_bottom'></view>
<view class='absolute inner_item left_bottom'></view>
</view>
<view class='bg_dark main_item full-height' style='width:{{margin.right + "px"}}'></view>
</view>
<view class='bg_dark out_item flex-column flex-end'>
<view class='flex-around text_white text_bg'>
<view catchtap='outputImg' data-type='1'><text>重新上传</text></view>
<view catchtap='getImg'><text>选择图片</text></view>
</view>
</view>
<!-- -->
<view class='absolute full-width full-height bg_black'></view>