在WebGL放大镜中使用鼠标滚轮进行缩放时无法保持适当的比例

时间:2016-10-25 07:15:51

标签: javascript webgl shader opengl-es-2.0 fabricjs

我正在实施一个工作正常的webgl放大镜。 但是当我使用鼠标滚轮应用变焦时,它会扭曲。 我正在使用fabric.js并且fcanvas.getZoom()返回我用来缩放放大镜的当前缩放级别。

这里是codepen。 任何人都可以检查为什么它在使用鼠标滚轮放大时不起作用。

代码:

`

  MainCanvas = (function() {
    function MainCanvas(image, WIDTH, HEIGHT) {
      var err;
      this.image = image;
      this.WIDTH = WIDTH != null ? WIDTH : 128;
      this.HEIGHT = HEIGHT != null ? HEIGHT : 128;
      this.mouseout = bind(this.mouseout, this);
      this.mouseover = bind(this.mouseover, this);
      this.mousemove = bind(this.mousemove, this);
      this.render = bind(this.render, this);
      zoomcanvas = $(document.createElement('canvas'));
      zoomcanvas.css({
        'position': 'absolute',
        'width': this.WIDTH,
        'height': this.HEIGHT,
        'z-index': '1000',
        'border': '3px solid rgba(0,0,0,0.4)',
        'border-radius': '50%',
        'box-shadow': '2px 2px 16px 2px #223',
        'pointer-events': 'none' 
      });
      $('#canvases').append(zoomcanvas);
      med = [0.5, 0.5];
      this.scaled = 1;
      try {
        this.gl = zoomcanvas[0].getContext("experimental-webgl") || zoomcanvas[0].getContext("webgl");
      } catch (_error) {
        err = _error;
        console.log(err.message);
        alert(err.message);
      }
      this.gl.clearColor(0.8, 0.8, 0.8, 1.0);
      this.mouse = {
        x: .5,
        y: .5
      };
      this.mvMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
      this.pMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
      this.data = {};
      this.initShaders();
      this.initBuffers();
      this.initImages();
      this.render();
      this.image.mousemove(this.mousemove);
      this.image.mouseover(this.mouseover).mouseout(this.mouseout);
    }

    MainCanvas.prototype.initShaders = function() {
      var fragmentShader, vertexShader;
      fragmentShader = this.getShader('shader-fs');
      vertexShader = this.getShader('shader-vs');
      this.shaderProgram = this.gl.createProgram();
      this.gl.attachShader(this.shaderProgram, vertexShader);
      this.gl.attachShader(this.shaderProgram, fragmentShader);
      this.gl.linkProgram(this.shaderProgram);
      if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
        console.log('Não pode inicializar shaders!');
      }
      this.gl.useProgram(this.shaderProgram);
      this.data.vertexPositionAttribute = this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
      this.gl.enableVertexAttribArray(this.data.vertexPositionAttribute);
      this.data.textureCoordAttribute = this.gl.getAttribLocation(this.shaderProgram, "aTextureCoord");
      this.gl.enableVertexAttribArray(this.data.textureCoordAttribute);
      this.data.samplerUniform0 = this.gl.getUniformLocation(this.shaderProgram, "sampler0");
      this.data.medUniform = this.gl.getUniformLocation(this.shaderProgram, "med");
      this.data.scaledUniform = this.gl.getUniformLocation(this.shaderProgram, "scaled");
    };

    MainCanvas.prototype.setMatrixUniforms = function() {
      var normalMatrix;
      this.gl.uniformMatrix4fv(this.data.pMatrixUniform, false, this.pMatrix);
      this.gl.uniformMatrix4fv(this.data.mvMatrixUniform, false, this.mvMatrix);
      normalMatrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
      return this.gl.uniformMatrix3fv(this.data.nMatrixUniform, false, normalMatrix);
    };

    MainCanvas.prototype.getShader = function(id) {
      var k, shader, shaderScript, str;
      shaderScript = document.getElementById(id);
      if (shaderScript === null) {
        return false;
      }
      str = '';
      k = shaderScript.firstChild;
      while (k) {
        if (k.nodeType === 3) {
          str += k.textContent;
        }
        k = k.nextSibling;
      }
      if (shaderScript.type === "x-shader/x-fragment") {
        shader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
      } else {
        shader = this.gl.createShader(this.gl.VERTEX_SHADER);
      }
      this.gl.shaderSource(shader, str);
      this.gl.compileShader(shader);
      if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
        console.log(this.gl.getShaderInfoLog(shader));
        return false;
      }
      return shader;
    };

    MainCanvas.prototype.initBuffers = function() {
      return this.bufferPlane();
    };

    MainCanvas.prototype.bufferPlane = function() {
      var buffer, colors, indices, normais, uv, vertices;
      vertices = [-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0];
      buffer = this.gl.createBuffer();
      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
      this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(vertices), this.gl.STATIC_DRAW);
      buffer.itemSize = 3;
      buffer.numItems = 4;
      this.data.vertexPositionBuffer = buffer;
      normais = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1];
      buffer = this.gl.createBuffer();
      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
      this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(normais), this.gl.STATIC_DRAW);
      buffer.itemSize = 4;
      buffer.numItems = 4;
      this.data.vertexColorBuffer = buffer;
      uv = [0, 0, 1, 0, 0, 1, 1, 1];
      buffer = this.gl.createBuffer();
      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
      this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(uv), this.gl.STATIC_DRAW);
      buffer.itemSize = 2;
      buffer.numItems = 4;
      this.data.vertexTextureCoordBuffer = buffer;
      indices = [0, 1, 2, 2, 3, 1];
      buffer = this.gl.createBuffer();
      this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, buffer);
      this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this.gl.STATIC_DRAW);
      buffer.itemSize = 1;
      buffer.numItems = 6;
      return this.data.vertexIndexBuffer = buffer;
    };

    MainCanvas.prototype.handleTexture = function(texture) {
      this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
      this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);
      this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, canvas);
      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
      this.gl.bindTexture(this.gl.TEXTURE_2D, null);
      this.scaled = Math.max(this.WIDTH / this.image.width(), this.HEIGHT / this.image.height());
      return this.scaled / (fcanvas.getZoom());
    };

    MainCanvas.prototype.initImages = function() {
      this.data.texture0 = this.gl.createTexture();
      this.handleTexture(this.data.texture0);
    };

    MainCanvas.prototype.render = function(t) {
      this.gl.viewport(0, 0, zoomcanvas[0].width, zoomcanvas[0].height);
      this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
      this.gl.uniform1f(this.data.scaledUniform, this.scaled / fcanvas.getZoom() / 2);
      this.gl.uniform2f(this.data.medUniform, parseFloat(med[0]) , parseFloat(med[1]));
      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.data.vertexPositionBuffer);
      this.gl.vertexAttribPointer(this.data.vertexPositionAttribute, this.data.vertexPositionBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.data.vertexTextureCoordBuffer);
      this.gl.vertexAttribPointer(this.data.textureCoordAttribute, this.data.vertexTextureCoordBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
      this.gl.activeTexture(this.gl.TEXTURE0);
      this.gl.bindTexture(this.gl.TEXTURE_2D, this.data.texture0);
      this.gl.uniform1i(this.data.samplerUniform0, 0);
      this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.data.vertexIndexBuffer);
      this.setMatrixUniforms();
      return this.gl.drawElements(this.gl.TRIANGLES, this.data.vertexIndexBuffer.numItems, this.gl.UNSIGNED_SHORT, 0);
    };

    MainCanvas.prototype.mousemove = function(e) {
          var o2, x, y;
          o2 = this.image.offset();
          x = (e.offsetX + o2.left);
          y = (e.offsetY + o2.top);
          zoomcanvas.css({
            'left': parseInt(x - this.WIDTH * 0.5),
            'top': parseInt(y - this.HEIGHT * 0.5)
          });
          med[0] = (((e.offsetX - imageAttrs.left) ) / (oImg.width));
          med[1] = (1.0 - (((e.offsetY - imageAttrs.top)) / (oImg.height)));
          $('body').css('cursor', 'none');
          return this.render();
     };

    MainCanvas.prototype.mouseover = function(e) {
      return zoomcanvas.show();
    };

    MainCanvas.prototype.mouseout = function(e) {
      return zoomcanvas.fadeOut("fast");
    };

    return MainCanvas;

  })();

  window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
    return window.setTimeout(callback, 40);
  };

  window.onload = function(e) {
    var mainCanvas;
    console.clear();
    console.log(Date.now());
    var width = $("#sampler0")[0].width; var height = $("#sampler0")[0].height;
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext('2d');
    var AR = calculateAspectRatio(width, height);
    ctx.drawImage($("#sampler0")[0], 0, 0, AR.renderableWidth, AR.renderableHeight);
    var scaleX = AR.renderableWidth / width;
    var scaleY = AR.renderableHeight / height;
    oImg = new fabric.Image(canvas, 
    {
        selectable : false,
        width : width,
        height : height,
        lockUniScaling: true,
        centeredScaling: true,
        scaleX : scaleX,
        scaleY : scaleY,
        alignX : "mid",
        alignY : "mid",
    });
    fcanvas.add(oImg);
    ///bring image to center
    fcanvas.centerObject(oImg);
    /////////////////////////////////////////////////////////
    ///scale image back to default
    oImg.scaleX = 1;
    oImg.scaleY = 1;
    ///get left and top for zooming correctly.
    imageAttrs.scaleX = scaleX;
    fcanvas.zoomToPoint({ x: oImg.left, y: oImg.top }, scaleX);
    oImg.on('mouseout', function(event) {
        zoomcanvas.fadeOut("fast");
    });
    oImg.on('mouseover', function(event) {
        zoomcanvas.show();
    });
    imageAttrs.left = oImg.left;
    imageAttrs.top = oImg.top;
    fcanvas.renderAll();
    applyZoom();
    return mainCanvas = new MainCanvas($("#canvases"), 256, 256);
  };

  var calculateAspectRatio = function (width, height) {
        var imageAspectRatio = width / height;
        var canvasAspectRatio = windowWidth / windowHeight;
        var renderableHeight, renderableWidth, xStart, yStart;
        var AR = new Object();
        /// If image's aspect ratio is less than canvas's we fit on height
        /// and place the image centrally along width
        if(imageAspectRatio < canvasAspectRatio) {
            renderableHeight = windowHeight ;
            renderableWidth = width * (renderableHeight / height);
            xStart = (windowWidth - renderableWidth) / 2;
            yStart = 0;
        }

        /// If image's aspect ratio is greater than canvas's we fit on width
        /// and place the image centrally along height
        else if(imageAspectRatio > canvasAspectRatio) {
            renderableWidth = $(window).width()
            renderableHeight = height * (renderableWidth / width);
            xStart = 0;
            yStart = ( windowHeight  - renderableHeight) / 2;
        }

        ///keep aspect ratio
        else {
            renderableHeight =  windowHeight ;
            renderableWidth = windowWidth;
            xStart = 0;
            yStart = 0;
        }
        AR.renderableHeight = renderableHeight;
        AR.renderableWidth = renderableWidth;
        return AR;
    }

  /**
   * Used to apply Zooming on the canvas.
   */
  var applyZoom = function () {
    var canvasarea = document.getElementById("canvases");
    if (canvasarea.addEventListener) {
        // IE9, Chrome, Safari, Opera
        canvasarea.addEventListener("mousewheel", zoom, false);
        // Firefox
        canvasarea.addEventListener("DOMMouseScroll", zoom, false);
    }
    // IE 6/7/8
    else canvasarea.attachEvent("onmousewheel", zoom);
    return this;
  }

  function zoom(e) {  
        var evt=window.event || e;
        var delta = evt.detail? evt.detail*(-120) : evt.wheelDelta;
        var curZoom = fcanvas.getZoom(),  newZoom = curZoom + delta / 4000,
        x = e.offsetX, y = e.offsetY;
        //applying zoom values.
        fcanvas.zoomToPoint({ x: x, y: y }, newZoom);
        if(e != null)e.preventDefault();
        return false;
  }


}).call(this);`

由于

0 个答案:

没有答案