首页 > 解决方案 > p5js - 在平移/缩放中钳制图像

问题描述

使用 p5js,我正在开发一个平移/缩放功能,它允许您平移/缩放图像,然后钳住图像的边缘。我遇到的主要问题是夹紧图像的边缘,因此您永远不能将图像拖过容器的边缘。例如:

松开 夹紧
在此处输入图像描述 在此处输入图像描述

注意未夹紧图像中的黑色背景。当我拖动图像时,它绝不应该允许我将图像角拖过画布边缘。

以下是我目前处理各种事件和 p5js 设置的方式:

 /* eslint-disable no-undef, no-unused-vars */

var img;
var w, h, currentImageWidth, currentImageHeight;
var x, y, tox, toy;
var zoom = 0.01; //zoom step per mouse tick

function preload() {
  img = loadImage("https://i.imgur.com/MBFJhju.jpeg", () => {});
}

function setup() {
  createCanvas(600, 600);
  w = currentImageWidth = 600;
  h = currentImageHeight = 600;
  x = tox = w / 2;
  y = toy = h / 2;
}

function draw() {
  background(0);

  //tween/smooth motion
  x = lerp(x, tox, 0.1);
  y = lerp(y, toy, 0.1);
  w = lerp(w, currentImageWidth, 0.1);
  h = lerp(h, currentImageHeight, 0.1);

  image(img, x - w / 2, y - h / 2, w, h);
}

function mouseDragged() {
  let maxX = currentImageWidth;
  let minX = -1 * maxX;
  let maxY = currentImageHeight;
  let minY = -1 * maxY;
  let nextXposition = tox + mouseX - pmouseX;
  let nextYposition = toy + mouseY - pmouseY;
  if (
    nextXposition - currentImageWidth * 0.5 < maxX &&
    nextXposition - currentImageWidth * 0.5 > minX
  ) {
    tox += mouseX - pmouseX;
  }
  if (
    nextYposition - currentImageHeight * 0.5 < maxY &&
    nextYposition - currentImageHeight * 0.5 > minY
  ) {
    toy += mouseY - pmouseY;
  }
}

function mouseWheel(event) {
  var e = event.wheelDeltaY;
  console.log(event);
  if (e > 0) {
    //zoom in
    for (let i = 0; i < e; i++) {
      if (currentImageWidth > 3 * width) return; //max zoom
      tox -= zoom * (mouseX - tox);
      toy -= zoom * (mouseY - toy);
      currentImageWidth *= zoom + 1;
      currentImageHeight *= zoom + 1;
    }
  }

  if (e < 0) {
    //zoom out
    for (let i = 0; i < -e; i++) {
      if (currentImageWidth < width) return; //min zoom
      tox += (zoom / (zoom + 1)) * (mouseX - tox);
      toy += (zoom / (zoom + 1)) * (mouseY - toy);
      currentImageHeight /= zoom + 1;
      currentImageWidth /= zoom + 1;
    }
  }
  //adjust x and y if out of bounds
  let maxX = width * 0.5;
  let minX = -1 * maxX;
  let maxY = height * 0.5;
  let minY = -1 * maxY;
  let diff = 0;
  if (currentImageWidth + currentImageWidth * 0.5 <= maxX) {
    diff = maxX - (tox + currentImageWidth * 0.5);
    tox += diff;
  }
  if (currentImageWidth - currentImageWidth * 0.5 >= minX) {
    diff = currentImageWidth - currentImageWidth * 0.5 - minX;
    tox -= diff;
  }
  if (toy + currentImageHeight * 0.5 <= maxY) {
    diff = maxY - (toy + currentImageHeight * 0.5);
    toy += diff;
  }
  if (toy - currentImageHeight * 0.5 >= minY) {
    diff = toy - currentImageHeight * 0.5 - minY;
    toy -= diff;
  }

  return false;
}

目前,夹子实际上不起作用。但是您可以拖动图像并缩放。我的意图是让它像在游戏中的地图上平移/缩放一样工作。

我相信主要的痛点是mouseDragged事件处理程序,我认为我将使用mouseWheel事件处理程序处理钳位的方式将适用于缩放事件。

如果您需要任何其他信息,请告诉我!

完整演示:

https://codesandbox.io/embed/great-dirac-yvd0s?fontsize=14&hidenavigation=1&theme=dark

标签: javascriptp5.js

解决方案


我最近在 processing.org 论坛上回答了一个类似的问题

  • 为了保证图像的左边缘不比视图区域的左边缘更靠右,显示图像的x位置不能大于图像宽度除以2
  • 为了保证图像的右边缘不比视图区域的右边缘更左,图像显示的x位置不能小于视图区域的宽度减去视图区域宽度的一半。图片。
  • 纵轴的逻辑是一样的。图像的 y 位置必须介于视图高度减去图像高度的一半和图像宽度的一半之间。

var img;
var w, h, currentImageWidth, currentImageHeight;
var x, y, tox, toy;
var zoom = 0.01; //zoom step per mouse tick

function preload() {
  img = loadImage("https://i.imgur.com/MBFJhju.jpeg");
}

function setup() {
  createCanvas(300, 300);
  w = currentImageWidth = 300;
  h = currentImageHeight = 300;
  x = tox = w / 2;
  y = toy = h / 2;
}

function draw() {
  background(0);

  //tween/smooth motion
  x = lerp(x, tox, 0.1);
  y = lerp(y, toy, 0.1);
  w = lerp(w, currentImageWidth, 0.1);
  h = lerp(h, currentImageHeight, 0.1);

  image(img, x - w / 2, y - h / 2, w, h);
}

function mouseDragged() {
  let maxX = currentImageWidth / 2;
  let minX = width - maxX;
  let maxY = currentImageHeight / 2;
  let minY = height - maxY;
  
  console.log(JSON.stringify({minX, maxX,minY,maxY}));
  tox = constrain(tox + mouseX - pmouseX, minX, maxX);
  toy = constrain(toy + mouseY - pmouseY, minY, maxY);
}

function mouseWheel(event) {
  var delta = event.wheelDeltaY;
  // console.log(event);
  
  // TODO: figure out where on the image the mouse cursor is
  // Figure how how much that point will shift based on the scale
  // Adjust the tox and toy to compensate (thus keeping the part of the image where the mouse is stationary.
  
  currentImageWidth *= delta * zoom + 1;
  currentImageHeight *= delta * zoom + 1;
  
  // Check constraints
  if (delta > 0) {
    //zoom in
    if (currentImageWidth > 3 * width) {
      currentImageWidth = 3 * width;
      currentImageHeight = 3 * height;
      //max zoom
    }
  } else if (delta < 0) {
    //zoom out
    if (currentImageWidth < width) {
      //min zoom
      currentImageWidth = width;
      currentImageHeight = height;
    }
  }
  
  //adjust x and y if out of bounds
  let maxX = currentImageWidth / 2;
  let minX = width - maxX;
  let maxY = currentImageHeight / 2;
  let minY = height - maxY;
  
  tox = constrain(tox, minX, maxX);
  toy = constrain(toy, minY, maxY);

  return false;
}
html,
body {
  height: 100%;
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>


推荐阅读