使用svg和canvas实现图片的剪切

最近工作项目上需要实现一个对图片进行多次剪切,并上传服务器的功能。要求可以在图片上增加用户交互,进行一些增删改查的操作
一. 图片的渲染,用canvas还是svg
svg的对象级别操作使得在图片中添加dom组件用于用户交互变得方便,但是svg不提供对图片像素级别的处理,无法获取特定位置的图片像素数据,因此图片的剪切后上传的功能需要使用canvas,canvas提供toDataURL的api可以获取指定位置的base64。因此使用svg和结合的方案,svg用于图片显示和剪切的操作,以及用户交互的dom操作,canvas用户获取剪切图片的数据
二. 具体实现

  1. 图片渲染
    { this.myCanvas = e; }} id="svgId" xmlns="http://www.w3.org/2000/svg" width={finalWidth + 'px'} height={finalHeight + 'px'} viewBox={viewBox1}>
    rotate(${this.state.rotation[this.state.showUrlIndex]}deg), transformOrigin: 'center' }}>

  2. 图片的剪切操作
    对svg dom节点绑定三个鼠标操作事件,实现画矩形的操作:
    svg.onmousedown = function () {
    let ce = ev || event;
    // 获取鼠标点击后的坐标
    x1 = ce.offsetX;
    y1 = ce.offsetY;
    }
    svg.onmousemove = function (ev) {
    const nx1 = ce.offsetX;
    const ny1 = ce.offsetY;
    xOffset = nx1 - x1; // 相对鼠标一开始点下的x偏移
    yOffset = ny1 - y1;
    that.drawRect(svg, x1, y1, xOffset, yOffset, id); // 画矩形
    };
    svg.onmouseup = function (ev) {
    svg.onmousemove = null;
    };
    drawRect = (svg, px, py, width, height, id) =>{
    // 删除之前画的矩形(边画边删除,否则会出现层叠在一起的矩形)
    let delRect = document.getElementById(id);
    if (delRect != null) {
    delRect.remove();
    }
    // 创建矩形
    if (px >= 0 && py >= 0 && width >= 0 && height >= 0) {
    const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    // 画矩形
    rect.setAttribute("id", id);
    rect.setAttribute("x", px);
    rect.setAttribute("y", py);
    rect.setAttribute("width", width);
    rect.setAttribute("height", height);
    rect.setAttribute("style", "fill:rgb(0,0,0);stroke-width:1;stroke:rgb(255,0,255);fill-opacity:0;");
    // 将绘制好的矩形添加到svg中
    svg.appendChild(rect);

}

}

  1. 获取剪切数据,上传服务器
    获取剪切数据主要使用canvas的toDataUrl功能
    var tnCanvas = document.createElement('canvas');
    var tnCanvasContext = tnCanvas.getContext('2d');
    tnCanvas.width = imgWidth + 10; // imgWidth为剪切的小图片尺寸
    tnCanvas.height = imgHeight + 10;
    tnCanvasContext.drawImage(image, startX, startY, newWidth * ratio, newHeight * ratio, 0, lastHeight, newWidth, newHeight); // image为大图的image对象
    const dataurl = tnCanvas.toDataURL(); // 将画布上小题的图片转成base64
    this.dataURLtoFile(dataurl, number + '.png'); // base64 转为file 对象可上传至服务器

你可能感兴趣的:(使用svg和canvas实现图片的剪切)