Kinetic JS image Magnifier

2019-08-17 13:00发布

问题:

I am trying to follow this example http://www.script-tutorials.com/html5-canvas-image-zoomer/

I get the following error:

Object doesn't support property or method 'getContext'

here is my script:

 stage = new Kinetic.Stage({
            container: 'container',
            width: 512,
            height: 512
        });
        var layer = new Kinetic.Layer();

        var imageObj = new Image();
        imageObj.onload = function() {
            var yoda = new Kinetic.Image({
                x: 0,
                y: 0,
                image: imageObj,
                width: 512,
                height: 512
            });
            layer.add(yoda);
            stage.add(layer);
        };
        imageObj.src = "../../Content/images/notfound.png";
        canvas = document.getElementById('container');
        ctx = canvas.getContext('2d');

Would appreciate your suggestions or is there an example for image magnifier for Kinetic. Thanks in advance

回答1:

When you did the following, it gets the div element hosting kineticjs...it doesn't get a canvas.

canvas = document.getElementById('container');

That's why your call to getContext fails.

[Edited to include an example of magnification using Kinetic's custom Shape]

We can use the Kinetic Shape object which is designed to allow us to do custom drawing.

We can custom draw anything in the drawFunc function because we have access to the canvas context.

drawfunc will be called every time the custom Shape needs to be redrawn.

Here is the Kinetic custom Shape object in outline form:

zoomer = new Kinetic.Shape({

    // The drawFunc lets us do custom drawings because are given the canvas

    drawFunc: function(canvas) {

        // We can use the canvas context

        var ctx = canvas.getContext();
        ctx.beginPath();

        // now we make any custom drawings
        // *** put custom drawing code here ***


        // but we must finish with this Kinetic-specific fillStroke(this)
        // to render the drawing (not optional!)

        canvas.fillStroke(this);
    }
});

Now for some zoomer specifics.

First, use a temporary html canvas to create a copy of the image at ½ resolution:

var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");

canvas.width=image.width/2;
canvas.height=image.height/2;
ctx.drawImage(image,
    0,0,image.width,image.height,
    0,0,image.width/2,image.height/2);

In the drawFunc function of the Shape, draw a rectangle containing the half-resolution image.

Notice that drawFunc must conclude with canvas.fillStroke(this)

canvas.fillStroke(this) is a KineticJS specific command that renders the drawings and it is required.

zoomer = new Kinetic.Shape({
    drawFunc: function(canvas) {
        var ctx = canvas.getContext();
        ctx.beginPath();

        ctx.rect( 0,0, image.width/2, image.height/2 );
        ctx.drawImage(halfCanvas,0,0);

        canvas.fillStroke(this);
    },
});

If the mouse is down, also draw the zoom viewer with a cropped portion of the full size image.

if(this.MouseIsDown){
    ctx.rect(mouseX,mouseY,viewerSize,viewerSize);
    ctx.drawImage(image,
        mouseX, mouseY, viewerSize, viewerSize,
        this.mouseX,this.mouseY, viewerSize, viewerSize);
}

That’s it...See the code below for some fine-points and styling.

Here’s a Fiddle that must be viewed in Chrome or Mozilla (IE=CORS exception): http://jsfiddle.net/m1erickson/dMr8g/

Here is example code:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.3.min.js"></script>

<style>
    body{ background-color: ivory; padding:30px; }
    #container{ width:200px; height:200px; border:1px solid red;}
</style>

<script>
$(function(){

  var stage = new Kinetic.Stage({
    container: 'container',
    width: 200,
    height: 200
  });
  var layer = new Kinetic.Layer();
  stage.add(layer);

  // create an image to zoom
  var zoomImage=new Image();
  var halfCanvas=document.createElement("canvas");
  var halfCtx=halfCanvas.getContext("2d");
  var width;
  var height;
  var halfWidth;
  var halfHeight;
  var zoomer;
  var zSize=60;
  var zOffset=zSize/2;

  zoomImage.onload=function(){
      width=zoomImage.width;
      height=zoomImage.height;
      halfWidth=width/2;
      halfHeight=height/2;
      halfCanvas.width=halfWidth;
      halfCanvas.height=halfHeight;
      halfCtx.drawImage(zoomImage,
          0,0,width,height,
          0,0,halfWidth,halfHeight);
      addZoomer();
  }
  zoomImage.src="yourImage.png";

  function addZoomer(image){

      zoomer = new Kinetic.Shape({
          drawFunc: function(canvas) {
              var ctx = canvas.getContext();
              ctx.beginPath();

              ctx.rect(zOffset,zOffset,halfWidth,halfHeight);
              ctx.drawImage(halfCanvas,zOffset,zOffset);

              if(this.MouseIsDown){
                  var ix=this.mouseX*2-zOffset;
                  var iy=this.mouseY*2-zOffset;
                  // adjust if zoom is off the image
                  if(ix<0){ ix=0; };
                  if(ix>width){ ix=width-zSize; };
                  if(iy<0){ iy=0; };
                  if(iy>height){ iy=height-zSize; };
                  ctx.rect(this.mouseX,this.mouseY,zSize,zSize);
                  ctx.drawImage(zoomImage,
                      ix,iy,zSize,zSize,
                      this.mouseX,this.mouseY,zSize,zSize);
              }
              canvas.fillStroke(this);
          },
          x:0,
          y:0,
          width:halfWidth,
          height:halfHeight,
          id: "zoomer",
          stroke:"blue",
          strokeWidth:2
      });
      zoomer.zoomImage=
      zoomer.MouseIsDown=false;
      zoomer.mouseX=0;
      zoomer.mouseY=0;

      zoomer.on('mousedown', function(e) {
          var mouseXY=stage.getMousePosition();
          this.mouseX=mouseXY.x-zOffset;
          this.mouseY=mouseXY.y-zOffset;
          this.MouseIsDown=true;
          layer.draw();
      });
      zoomer.on('mouseup', function(e) {
          this.MouseIsDown=false;
          layer.draw();
      });

      layer.add(zoomer);
      layer.draw();
  }


}); // end $(function(){});
</script>

</head>

<body>
    <div id="container"></div>
</body>
</html>