Open kitewhere opened 6 years ago
项目有个照片拼接功能 选取几张照片放上照片墙 照片可以拖动旋转缩放 最后生成一张拼接图片保存到服务器
image 直接绘制在 canvas 上 canvas 监听事件 然后根据鼠标坐标判断要操作哪个 image 和执行哪种操作 鼠标点击 image 的四个顶点的4个区域触发缩放和旋转 其他位置触发拖动操作 image 每次变形操作时 重绘 canvas image 在变形时 canvas 会频繁重绘 为了性能一共分了3层 canvas
这个方案的难点在于判断当前操作的 image 也就是鼠标点击的位置位于哪个 image 的范围内 对于这种四边形 还是比较好判断的 判断 m 在 tl tr bl br 四个顶点的范围内即可(其实 就是 point in polygon 问题的一个特例 ) 无非在计算4个顶点的时候 要考虑到缩放和旋转 三角函数的知识
最后生成拼接图片时把所有图片都绘制到 top 层 然后生成 base64 发回后端即可
鼠标事件可以直接绑定到每个 item 上 item 的结构可以这样写
.item img .tl .tr .bl .br
比方案1优在不用自己计算鼠标位置判断操作元素 item 的旋转缩放移动操作算法和方案1一样 只不过具体实现换成 css 的 transform (要注意transform的先后顺序)
最后调用 html2canvas 把 div 画布 转成 canvas 再得到 base64
其实对于这类简单的 dom 结构 不用 html2canvas 自己遍历 dom 取到 transform 信息 再绘制到 canvas 即可
和方案2类似 只是不用自己遍历 dom 只要把整个 dom 结构塞进 svg 的 里即可 不过最后还是要用canvas 转成 base64
优点就是特别方便 缺点就是 ie 不兼容 foreignobject
function getBase64(img){ var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var width = img.width, height = img.height; // canvas绘制 canvas.width = width; canvas.height = height; // 画布清除 context.clearRect(0, 0, width, height); // 绘制图片到canvas context.drawImage(img, 0, 0); return canvas.toDataURL(); } function html2Svg (domStr) { //创建模版字符串 var svgXML= `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <foreignObject width="100%" height="100%">${generateXML(html)}</foreignObject> </svg>` //利用Blob创建svg var svg = new Blob([svgXML], {type: 'image/svg+xml'}) //利用DOMURL.createObjectURL取出对象 var url = window.URL.createObjectURL(svg); var img = new Image() img.src = url return img } // 由于`foreignObject`只能引用XML文档, // 所以我们需要对DOM进行格式化 function generateXML (domStr) { var doc = document.implementation.createHTMLDocument(''); doc.write(html); doc.documentElement.setAttribute('xmlns', doc.documentElement.namespaceURI); doc = parseStyle(doc) console.log(doc) html = (new XMLSerializer).serializeToString(doc).replace('<!DOCTYPE html>',''); return html }
方案1 的难点在于判断鼠标位置 以及绘制有些繁琐 不过有些 cavans 库 做了封装 比如 createJs 操作起来还算方便 方案3 兼容性一票否决
所以最后还是方案2最好用
问题
项目有个照片拼接功能 选取几张照片放上照片墙 照片可以拖动旋转缩放 最后生成一张拼接图片保存到服务器
方案1 canvas
image 直接绘制在 canvas 上 canvas 监听事件 然后根据鼠标坐标判断要操作哪个 image 和执行哪种操作 鼠标点击 image 的四个顶点的4个区域触发缩放和旋转 其他位置触发拖动操作 image 每次变形操作时 重绘 canvas image 在变形时 canvas 会频繁重绘 为了性能一共分了3层 canvas
这个方案的难点在于判断当前操作的 image 也就是鼠标点击的位置位于哪个 image 的范围内 对于这种四边形 还是比较好判断的 判断 m 在 tl tr bl br 四个顶点的范围内即可(其实 就是 point in polygon 问题的一个特例 ) 无非在计算4个顶点的时候 要考虑到缩放和旋转 三角函数的知识
最后生成拼接图片时把所有图片都绘制到 top 层 然后生成 base64 发回后端即可
方案2 html2canvas
鼠标事件可以直接绑定到每个 item 上 item 的结构可以这样写
比方案1优在不用自己计算鼠标位置判断操作元素 item 的旋转缩放移动操作算法和方案1一样 只不过具体实现换成 css 的 transform (要注意transform的先后顺序)
最后调用 html2canvas 把 div 画布 转成 canvas 再得到 base64
其实对于这类简单的 dom 结构 不用 html2canvas 自己遍历 dom 取到 transform 信息 再绘制到 canvas 即可
方案3 svg foreignobject
和方案2类似 只是不用自己遍历 dom 只要把整个 dom 结构塞进 svg 的 里即可
不过最后还是要用canvas 转成 base64
优点就是特别方便 缺点就是 ie 不兼容 foreignobject
结论
方案1 的难点在于判断鼠标位置 以及绘制有些繁琐 不过有些 cavans 库 做了封装 比如 createJs 操作起来还算方便 方案3 兼容性一票否决
所以最后还是方案2最好用