将鼠标悬停在JS画布上以检测不同形状

时间:2019-03-25 10:12:57

标签: javascript jquery html5 canvas html5-canvas

我如何获得绘制路径的画布?通过JSON在30个矩形上方绘制我,但是如何在下面的函数中吸引我,将鼠标悬停在特定绘制的画布上后又改变背景?

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.globalAlpha = 0.7;
var grd = ctx.createLinearGradient(150, 2, 300, 200);
grd.addColorStop(0, "red");
grd.addColorStop(1, "red");
ctx.fillStyle = grd;
ctx.fillRect(200,200,200,200); 

$(canvas).hover(function() {
  $(this).css("background-color", "yellow");
  console.log(ctx);
},function() {
  $(this).css("background-color", "");
});

enter image description here

^这是它的外观。

我想在鼠标位于绘制元素上时更改背景

2 个答案:

答案 0 :(得分:0)

您可能需要对像素进行颜色编码,或者跟踪绘制的矩形,然后在鼠标移动时执行点到矩形的碰撞检查。

也许使用SVG而不是canvas会使您的任务更容易,因为SVG元素可以单独产生事件。

答案 1 :(得分:0)

我最近从事一些与在画布上绘制形状有关的工作。 希望以下代码段可以为您提供帮助! 抱歉,代码中缺少注释。有关更多详细信息,您可以直接问我

var CANVAS_FILL_COLOR_ARR = ["blue", "red", "purple", "yellow", "green", "gray", "orange"];

function PositionModel(x, y) {
  this.x = x;
  this.y = y;
}

PositionModel.prototype.fromJson = function (json) {
  if (Array.isArray(json)) {
    return new PositionModel(json[0], json[1]);
  } else {
    return new PositionModel(json.x, json.y);
  }
};


function RectangleShapeModel(x, y, w, h, fill) {
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;

  this.fill = fill || "#AAAAAA";
}

RectangleShapeModel.prototype.draw = function (ctx) {
  ctx.fillStyle = this.fill;
  ctx.fillRect(this.x, this.y, this.w, this.h);
};
RectangleShapeModel.prototype.contain = function (point) {
  return (this.x <= point.x) && (this.x + this.w >= point.x) &&
    (this.y <= point.y) && (this.y + this.h >= point.y);
};

RectangleShapeModel.prototype.getInfo = function () {
  return "x: " + this.x + ", y: " + this.y + ", w: " + this.w + ", h: " + this.h;
};

function CanvasStateModel(canvas, shapeData) {
  this.canvas = canvas;
  this.width = canvas.width;
  this.height = canvas.height;
  this.ctx = canvas.getContext("2d");
  this.shapeData = shapeData;
  var paddingLeft = "paddingLeft";
  var paddingTop = "paddingTop";
  var borderLeftWidth = "borderLeftWidth";
  var borderTopWidth = "borderTopWidth";
  if (document.defaultView && document.defaultView.getComputedStyle) {
    this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)[paddingLeft], 10) || 0;
    this.stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)[paddingTop], 10) || 0;
    this.styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)[borderLeftWidth], 10) || 0;
    this.styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)[borderTopWidth], 10) || 0;
  }
  // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
  // They will mess up mouse coordinates and this fixes that
  var html = document.body.parentNode;
  this.htmlTop = html.offsetTop;
  this.htmlLeft = html.offsetLeft;

  // **** Keep track of state! ****
  this.invalidState(); // when set to false, the canvas will redraw everything
  this.shapes = []; // the collection of things to be drawn

  // remove old events
  canvas.myState = this;
  canvas.removeEventListener("mousemove", this.mouseMoveListener, true);
  canvas.addEventListener("mousemove", this.mouseMoveListener, true);

  // **** Options! ****
  this.selectionColor = "#CC0000";
  this.selectionWidth = 2;
  this.drawInterval = 30;

  setInterval(function () {
    canvas.myState.draw();
  }, this.drawInterval);
}

CanvasStateModel.prototype.mouseMoveListener = function (e) {
  var myState = e.target.myState;
  var mouse = myState.getMouse(e);
  var containShape = myState.pointInShapes(mouse);
  if (containShape !== null) {
    $("#result-panel").css('background-color', containShape.fill);
  }
  myState.invalidState(); // Something"s dragging so we must redraw
};

CanvasStateModel.prototype.pointInShapes = function (point) {
  for (var i = this.shapes.length - 1; i >= 0; i--) {
    if (this.shapes[i].contain(new PositionModel(point.x, point.y))) {
      return this.shapes[i];
    }
  }
  return null;
};

CanvasStateModel.prototype.invalidState = function () {
  this.valid = false;
};

CanvasStateModel.prototype.addShape = function (shape) {
  this.shapes.push(shape);
  this.invalidState();
};

CanvasStateModel.prototype.clear = function () {
  this.ctx.clearRect(0, 0, this.width, this.height);
};

CanvasStateModel.prototype.drawShapes = function () {
  this.shapes = this.constructShapes();
  var l = this.shapes.length;
  for (var i = 0; i < l; i++) {
    var shape = this.shapes[i];
    // We can skip the drawing of elements that have moved off the screen:
    if (shape.x > this.width || shape.y > this.height ||
      shape.x + shape.w < 0 || shape.y + shape.h < 0) {
      continue;
    }
    this.shapes[i].draw(this.ctx);
  }
};

CanvasStateModel.prototype.draw = function () {
  // if our state is invalid, redraw and validate!
  if (!this.valid) {
    var ctx = this.ctx;
    // construct shapes from camera zone
    this.clear();
    this.drawShapes();

    // right now this is just a stroke along the edge of the selected Shape
    if (this.selection != null) {
      ctx.strokeStyle = this.selectionColor;
      ctx.lineWidth = this.selectionWidth;
      var mySel = this.selection;
      ctx.strokeRect(mySel.x, mySel.y, mySel.w, mySel.h);
    }
    // ** Add stuff you want drawn on top all the time here **
    this.valid = true;
  }
};

CanvasStateModel.prototype.constructShapes = function () {
  var shapes = [];
  for (var i = 0; i < this.shapeData.length; i++) {
    var shapeDataItem = this.shapeData[i];
    var fill = CANVAS_FILL_COLOR_ARR[i % CANVAS_FILL_COLOR_ARR.length];
    var shape = new RectangleShapeModel(shapeDataItem.x, shapeDataItem.y, shapeDataItem.w, shapeDataItem.h, fill);
    shapes.push(shape);
  }
  return shapes;
};

// Creates an object with x and y defined, set to the mouse position relative to the state"s canvas
// If you wanna be super-correct this can be tricky, we have to worry about padding and borders
CanvasStateModel.prototype.getMouse = function (e) {
  var element = this.canvas;
  var offsetX = element.offsetLeft;
  var offsetY = element.offsetTop;
  var mx;
  var my;
  // Compute the total offset
  if (element.offsetParent !== undefined) {
    var parentElement = element.offsetParent;
    while (parentElement) {
      offsetX += parentElement.offsetLeft;
      offsetY += parentElement.offsetTop;
      parentElement = parentElement.offsetParent;
    }
  }
  // Add padding and border style widths to offset
  // Also add the <html> offsets in case there"s a position:fixed bar
  offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
  offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;
  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;
  return {x: mx, y: my};
};

$(document).ready(function () {
  var canvas = $("#layout-canvas")[0];
  var shapeData = [{
    x: 100,
    y: 100,
    w: 100,
    h: 100
  }, {
    x: 300,
    y: 100,
    w: 200,
    h: 100
  }, {
    x: 500,
    y: 100,
    w: 50,
    h: 100
  }, {
    x: 700,
    y: 100,
    w: 80,
    h: 80
  }];

  function drawCanvas() {
    canvasState = new CanvasStateModel(canvas, shapeData);
    canvasState.invalidState();
  }

  drawCanvas();
});
#layout-canvas-wrapper {
  display: block;
}

#result-panel {
  width: 300px;
  height: 300px;
  display: block;
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="layout-canvas">
    <div id="layout-canvas-wrapper">
        <canvas id="layout-canvas" width="900" height="200"></canvas>
    </div>
    <div id="result-panel"></div>
</div>