JavaScript实现图片画板.rar

  • a6_843147
    了解作者
  • 690KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-05-27 03:36
    上传日期
JavaScript实现对图片进行锚点、拖动变形
JavaScript实现图片画板.rar
  • www
  • d3.v3.min.js
    139.6KB
  • BG.jpg
    35.9KB
  • numeric-1.2.6.min.js
    69.8KB
  • test-g.png
    582KB
  • index.html
    10.7KB
内容介绍
<script src="./d3.v3.min.js"></script> <script src="./numeric-1.2.6.min.js"></script> <p> Drag points around to distort image. <input type="checkbox" checked="1" id="drawSkeleton"></input> <label for="drawSkeleton">Draw wireframe and control points.</label> </p> <div id="container"> <canvas id="canvasElement"></canvas> <svg id="svgElement"></svg> </div> <style type="text/css"> #container { position: relative; width: 800px; height: 800px; } #container * { position: absolute; } #screen { visibility: hidden; } circle.control-point { fill: red; fill-opacity: 0.25; } circle.control-point:hover { stroke: yellow; stroke-width: 2px; } </style> <script type="text/javascript"> var maximumTriangleCount = 200; var maxAllowableBadness = 1e-2; // The control points which represent the top-left, top-right and bottom // right of the image. var controlPoints = [ { x: 100, y: 100 }, { x: 300, y: 100 }, { x: 300, y: 400 }, { x: 100, y: 400 } ]; var backgroundImgElement = document.getElementById('background'); var imgElement = document.getElementById('screen'); var canvasElement = document.getElementById('canvasElement'); var svgElement = document.getElementById('svgElement'); var drawSkeletonElement = document.getElementById('drawSkeleton'); var containerElement = document.getElementById('container') initialize(); function initialize() { drawSkeletonElement.onchange = redrawImg; imgElement.onload = redrawImg; backgroundImgElement.onload = resizeElements; resizeElements(); setupDragging(); redrawImg(); } function resizeElements() { var w = backgroundImgElement.naturalWidth; var h = backgroundImgElement.naturalHeight; containerElement.style.width = w+'px'; containerElement.style.height = h+'px'; svgElement.style.width = w+'px'; svgElement.style.height = h+'px'; canvasElement.width = w; canvasElement.height = h; redrawImg(); } function redrawImg() { var drawSkeleton = !!(drawSkeletonElement.checked); var w = imgElement.naturalWidth, h = imgElement.naturalHeight; var srcPoints = [ { x: 0, y: 0 }, // top-left { x: w, y: 0 }, // top-right { x: w-120, y: h-5 }, // bottom-right { x: 120, y: h-5 } // bottom-left ]; var ctx = canvasElement.getContext('2d'); ctx.clearRect(0, 0, canvasElement.width, canvasElement.height); var projPoints = findQuadProjectiveDepths(controlPoints); var triangles = [ { src: [srcPoints[0], srcPoints[1], srcPoints[2]], dst: [projPoints[0], projPoints[1], projPoints[2]] }, { src: [srcPoints[2], srcPoints[3], srcPoints[0]], dst: [projPoints[2], projPoints[3], projPoints[0]] } ]; // Keep sub-dividing until we're done var triIdx = 0; while((triIdx < triangles.length) && (triangles.length < maximumTriangleCount)) { var newTris = subdivideTriangle(triangles[triIdx]); if(newTris.length == 1) { // no subdivision performed triIdx++; } else { // remove original triangle and add new ones triangles.splice(triIdx, 1); triangles = triangles.concat(newTris); } } // Draw affine-transformed triangles for(var i=0; i<triangles.length; i++) { var src = triangles[i].src; var dstProj = triangles[i].dst; var dst = []; for(var j=0; j<dstProj.length; j++) { var p = dstProj[j]; dst.push({ x: p.x/p.z, y: p.y/p.z }); } var T = affineTransformationFromTriangleCorners(src, dst); ctx.save(); // set clip trianglePath(ctx, dst); ctx.clip(); // draw image ctx.transform(T[0], T[1], T[2], T[3], T[4], T[5]); ctx.drawImage(imgElement, 0, 0); ctx.restore(); if(drawSkeleton) { trianglePath(ctx, dst); ctx.lineWidth = 2; ctx.strokeStyle = '#080'; ctx.stroke(); } } if(drawSkeleton) { svgElement.style.visibility = 'visible'; } else { svgElement.style.visibility = 'hidden'; } } function subdivideTriangle(inputTri) { // Work out badness of each edge var worstEdge = { badness: -1, corners: null }; for(var cornerIdx=0; cornerIdx<inputTri.dst.length; cornerIdx++) { var corner1Idx = cornerIdx, corner2Idx = (cornerIdx+1) % inputTri.dst.length; var dz = inputTri.dst[corner1Idx].z - inputTri.dst[corner2Idx].z; var badness = Math.abs(dz); if(badness > worstEdge.badness) { worstEdge = { badness: badness, corners: [corner1Idx, corner2Idx] }; } } // If the maximum badness is OK, don't subdivide if(worstEdge.badness < maxAllowableBadness) { return [inputTri]; } // Going to turn // // A _____ B A __D__ B // \ / \/_\/ // \ / => F \ / E // C C var srcA = inputTri.src[0], dstA = inputTri.dst[0]; var srcB = inputTri.src[1], dstB = inputTri.dst[1]; var srcC = inputTri.src[2], dstC = inputTri.dst[2]; var srcD = { x: (srcA.x + srcB.x)/2, y: (srcA.y + srcB.y)/2 }; var dstD = { x: (dstA.x + dstB.x)/2, y: (dstA.y + dstB.y)/2, z: (dstA.z + dstB.z)/2 }; var srcE = { x: (srcB.x + srcC.x)/2, y: (srcB.y + srcC.y)/2 }; var dstE = { x: (dstB.x + dstC.x)/2, y: (dstB.y + dstC.y)/2, z: (dstB.z + dstC.z)/2 }; var srcF = { x: (srcC.x + srcA.x)/2, y: (srcC.y + srcA.y)/2 }; var dstF = { x: (dstC.x + dstA.x)/2, y: (dstC.y + dstA.y)/2, z: (dstC.z + dstA.z)/2 }; return [ { src: [ srcA, srcD, srcF ], dst: [ dstA, dstD, dstF ] }, { src: [ srcD, srcB, srcE ], dst: [ dstD, dstB, dstE ] }, { src: [ srcC, srcF, srcE ], dst: [ dstC, dstF, dstE ] }, { src: [ srcD, srcE, srcF ], dst: [ dstD, dstE, dstF ] }, ] } function findQuadProjectiveDepths(corners) { // See http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/ // Firstly, find the centre point: var centre = intersectLines( [corners[0], corners[2]], [corners[1], corners[3]]); // Lengths of diagonals var d02 = dist(corners[0], corners[2]); var d13 = dist(corners[1], corners[3]); // Find a projective homogeneous representation for each corner point // with the correct projective co-ordinate. See the site referenced in // the top comment for some more details. var tl_z = d02 / dist(corners[0], centre); var tl_hom = { x: tl_z * corners[0].x, y: tl_z * corners[0].y, z: tl_z }; var tr_z = d13 / dist(corners[1], centre); var tr_hom = { x: tr_z * corners[1].x, y: tr_z * corners[1].y, z: tr_z }; var br_z = d02 / dist(corners[2], centre); var br_hom = { x: br_z * corners[2].x, y: br_z * corners[2].y, z: br_z }; var bl_z = d13 / dist(corners[3], centre); var bl_hom = { x: bl_z * corners[3].x, y: bl_z * corners[3].y, z: bl_z }; return [ tl_hom, tr_hom, br_hom, bl_hom ]; } function trianglePath(ctx, points) { ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); ctx.lineTo(points[1].x, points[1].y); ctx.lineTo(points[2].x, points[2].y); ctx.closePath(); } function setupDragging() { // Use d3.js to provide user-draggable control points var rectDragBehav = d3.behavior.drag().on('drag', rectDragDrag); var dragT = d3
评论
    相关推荐