变形组件

变形组件

可以对目标元素进行类似ps的操作如:拖动,旋转,放大缩小

场景

自定义海报排版,自定义宣传页面
参考:做单页http://www.zuodanye.com/danyeeditor?tid=WTQX3VG2&event_uid=949811

我的思路

  1. 利用mousedown和mousemove和mouseup事件来实现拖拽
  2. 在拖拽基础上,实现基于绝对定位的选中,移动,旋转,伸缩四个动作

选中实现

发生在当前选中元素mousedown阶段,但是在document.documentElement的mousedown事件后

this.lastMouseX = e.pageX || e.clientX + document.documentElement.scrollLeft; // 鼠标位置
this.lastMouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
  1. 事件绑定在了元素本身以及document.documentElement上,并用捕获的方式从外到内的顺序,好处是:可以提前知道是否点击了当前元素,contains判断是否为当前的元素,并且判断接下来是移动|旋转|伸缩其中的哪个操作,记录好鼠标开始位置top和left
移动操作

发生在顶级元素mousemove阶段
1. 计算当前鼠标位置和上一次鼠标位置的差值,直接赋予目前元素:

// 鼠标移动后X值
const mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft;
const mouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
// 得出鼠标移动变化的位置值
let diffX = mouseX - this.lastMouseX + this.mouseOffX
let diffY = mouseY - this.lastMouseY + this.mouseOffY

this.elmX += diffX;
this.elmY += diffY;

新的top = 当前(旧的)top+差值top
新的left = 当前(旧的)left+差值left

旋转操作

发生在顶级元素mousemove阶段
1. 利用Math.atan2方法计算出旧的鼠标位置点到中心点的斜率(先拿到弧度值,再配合PI算出旧的弧度

const origin = this.getOrigin(); // 获取中心点
const lastAngle = Math.atan2(lastMouseY - origin.y, lastMouseX - origin.x); // 上一次鼠标距离中心点的斜率
const currentAngle = Math.atan2(mouseY - origin.y, mouseX - origin.x); // 本次斜率
rotateAngle += Math.round((currentAngle - lastAngle) * 180 / Math.PI); // 转成角度
this.props.rotating(rotateAngle);
this.setState({rotateAngle});

// atan2() 方法可返回从 x 轴到点 (x,y) 之间的角度。
// 返回值是-PI 到 PI 之间的值,是从 X 轴正向逆时针旋转到点 (x,y) 时经过的角
// 弧度=角度*Math.PI/180
2. 同样计算出新的鼠标离中心点的弧度
3. 两者相减得到最新的角度(0-360)之间

拉伸操作

发生在顶级元素mousemove阶段
1. 分两种情况,一种是旋转角度为0,一种是旋转角度不为0
2. 旋转角度为0: 和移动操作类似,如
向左拉长:

top不变
left不变
新的width = 当前(旧的)width + 差值left

向下拉长:

top不变
left不变
新的height = 当前(旧的)height+ 差值top 

3.旋转角度不为0:
- 需要结合当前角度计算出差值left和top,如45%时往下移动100px
相当于: 移动(斜边) = 差值top(对边) / (sin45° = 根号2)
这里写图片描述

top不变
left不变
新的height = 当前(旧的)height+ 差值top / sin45°

成果

http://www.weshowbest.net/scene/create
个人demo:https://wxwxnzm.github.io/

代码实例

https://github.com/wxwxnzm/react-h5-editor/blob/master/src/Drr/index.js

过程中遇到的难点

1,编辑时相对与画布左上角绝对定位,手机预览时如何适配不同屏幕?
2:如何处理scale放大后后节点的按钮被覆盖的问题?
3:如何把网页截图并下载?


1,编辑时相对与画布左上角绝对定位,手机预览时如何适配不同屏幕?
目前解决方案:
1:更改viewport,如根据编辑画布比例(320/640)和实际手机的宽高比例做整个网页的缩放。
例子:https://d.eqxiu.com/s/gRS81n6w
2:viewport不变,内容区根据比例做scale
例子:
http://www.weshowbest.net/preview/165
两者对比好坏探讨

2:如何处理scale放大后后节点的按钮被覆盖的问题?
http://www.weshowbest.net/scene/create
目前解决
用 getBoundingClientRect()方法动态计算放大后的高度,利用绝对定位,赋予按钮top值
探讨有无更好方案

3:如何把网页截图并下载?
https://github.com/niklasvh/html2canvas
利用html2canvas把dom转换成canvas并拿到canvas对象,再用toDataURL等api赋予a标签href并模拟点击(link.click())下载
拓展运用:canvas还可以用来上传图片(文件上传FormData对象)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值