3

有时候我们需要预览图片,对图片进行缩放平移等操作,这时候发现用img标签就不好用了。这时候就可以用我这个帖子的代码实现你要的效果。

格式支持:只要能在canvas上渲染的图片都能做缩放平移。

如果想缩放后还能把图片下载到本地,请自己调用canvas的api即可。

特性:小于canvas大小,则默认不缩放。大于canvas则以最长边为单位来缩放。

效果如下:
GIF.gif

将下方代码新建一个html,在浏览器打开就能看到效果:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图片绘制到Canvas上并能缩放和平移</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100vh;
        margin: 0;
      }

      canvas {
        border: 1px solid #000;
        margin-top: 20px;
      }
    </style>
  </head>

  <body>
    <h1>图片(jpg,png,svg,tiff...)绘制到Canvas上并能缩放和平移</h1>
    <input type="file" id="imageInput" accept="image/*" />
    <canvas id="canvas" width="600" height="600"></canvas>

    <script>
      var canvas, context
      var imageWidth, imageHeight
      var newWidth, newHeight
      var img,
        imgX = 0,
        imgY = 0,
        imgScale = 1
      document
        .getElementById("imageInput")
        .addEventListener("change", function (event) {
          const file = event.target.files[0]
          if (file) {
            ;(imgX = 0), (imgY = 0), (imgScale = 1)
            const reader = new FileReader()
            reader.readAsDataURL(file)
            reader.onload = function (e) {
              img = new Image()
              img.src = e.target.result
              img.onload = function () {
                const canvasWidth = canvas.width
                const canvasHeight = canvas.height
                const imageWidth = img.width
                const imageHeight = img.height

                // 计算缩放比例
                const scaleX = canvasWidth / imageWidth
                const scaleY = canvasHeight / imageHeight
                const sc = Math.min(scaleX, scaleY)
                const scale = sc > 1 ? 1 : sc
                // 计算新的图片尺寸
                newWidth = imageWidth * scale
                newHeight = imageHeight * scale

                // 计算图片在canvas中的位置
                imgX = (canvasWidth - newWidth) / 2
                imgY = (canvasHeight - newHeight) / 2
                drawImage()
                canvasEventsInit()
              }
            }
          }
        })
      function drawImage() {
        context.clearRect(0, 0, canvas.width, canvas.height)
        context.drawImage(
          img, //规定要使用的图像、画布或视频。
          0,
          0, //开始剪切的 x 坐标位置。
          img.width,
          img.height, //被剪切图像的高度。
          imgX,
          imgY, //在画布上放置图像的 x 、y坐标位置。
          newWidth * imgScale,
          newHeight * imgScale //要使用的图像的宽度、高度
        )
      }
      function canvasEventsInit() {
        canvas.onmousedown = function (event) {
          var pos = windowToCanvas(event.clientX, event.clientY)

          canvas.onmousemove = function (evt) {
            canvas.style.cursor = "move"
            var posl = windowToCanvas(evt.clientX, evt.clientY)
            var x = posl.x - pos.x
            var y = posl.y - pos.y
            pos = posl
            imgX += x
            imgY += y
            drawImage()
          }
          canvas.onmouseup = function () {
            canvas.onmousemove = null
            canvas.onmouseup = null
            canvas.style.cursor = "default"
          }
          document.onmouseup = function () {
            canvas.onmousemove = null
            canvas.onmouseup = null
            canvas.style.cursor = "default"
            document.onmouseup = null
          }
        }

        canvas.onmousewheel = canvas.onwheel = function (event) {
          var pos = windowToCanvas(event.clientX, event.clientY)
          var n = 1.1
          var n2 = (1 / 1.1).toFixed(2)
          event.wheelDelta = event.wheelDelta
            ? event.wheelDelta
            : event.deltalY * -40
          if (event.wheelDelta > 0) {
            imgScale *= n
            imgX = imgX * n - pos.x * (n - 1)
            imgY = imgY * n - pos.y * (n - 1)
          } else {
            imgScale *= n2
            imgX = imgX * n2 + pos.x * (1 - n2)
            imgY = imgY * n2 + pos.y * (1 - n2)
          }
          drawImage()
        }
      }

      /*坐标转换*/
      function windowToCanvas(x, y) {
        var box = canvas.getBoundingClientRect()
        return {
          x: x - box.left - (box.width - canvas.width) / 2,
          y: y - box.top - (box.height - canvas.height) / 2,
        }
      }
      ;(function int() {
        canvas = document.getElementById("canvas")
        canvas.width = canvas.getBoundingClientRect().width
        canvas.height = canvas.getBoundingClientRect().height
        context = canvas.getContext("2d")
      })()
    </script>
  </body>
</html>

这是个面向过程的代码。如感觉看起来写法垃圾,请自行修改成自己喜欢的样子。


smallStone
446 声望75 粉丝

前端一枚^_-