【问题标题】:KineticJS mouse event issueKineticJS 鼠标事件问题
【发布时间】:2012-08-29 02:25:05
【问题描述】:

我正在尝试使用 KineticJS 制作某种交互式地图,其中悬停的地方可以加载其他图像。但我不能让鼠标事件正常工作。事情是,一切正常但只有第一次鼠标悬停尝试,当我第二次悬停时,mouseout触发器不起作用:(

即当我第二次执行“mouseout”时,我希望地图部分再次变为浅蓝色(n_amer 图像),但它仍然是深蓝色(n_amer_sel 图像)。

这里是你可以看到这个错误的链接:http://kinlibtst.elitno.net/

非常感谢您的帮助!

代码:

  function loadImages(sources, callback) {
    var assetDir = 'PROJECT/';
    var images = {};
    var loadedImages = 0;
    var numImages = 0;
    for(var src in sources) {
      numImages++;
    }
    for(var src in sources) {
      images[src] = new Image();
      images[src].onload = function() {
        if(++loadedImages >= numImages) {
          callback(images);
        }
      };
      images[src].src = assetDir + sources[src];
    }
  }
  function initStage(images) {
    var stage = new Kinetic.Stage({
      container: 'container',
      width: 900,
      height: 452
    });

    var imagesLayer = new Kinetic.Layer();

    // img vars
    var n_amer = new Kinetic.Image({
      image: images.n_amer,
      x: 0,
      y: 0
    });

    var n_amer_sel = new Kinetic.Image({
      image: images.n_amer_sel,
      x: 0,
      y: 0
    });

    // mouse events
    n_amer.on('mouseover', function() {
        imagesLayer.add(n_amer_sel)
        stage.draw();
    });
    n_amer_sel.on('mouseout', function() {  
        imagesLayer.remove(n_amer_sel);
        stage.draw();
    });

    // imageBuffer for transparent pixels
    n_amer.createImageBuffer(function() {
      imagesLayer.drawBuffer();
    });
    n_amer_sel.createImageBuffer(function() {
      imagesLayer.drawBuffer();
    });        

    // add to stage
    imagesLayer.add(n_amer);
    stage.add(imagesLayer);
  }

  window.onload = function() {
    var sources = {
      n_amer: 'N-Amer.png',
      n_amer_sel: 'N-Amer_sel.png'
    };
    loadImages(sources, initStage);
  };

【问题讨论】:

    标签: javascript html canvas mouseover kineticjs


    【解决方案1】:

    不要使用新的图像对象,而是更改现有对象上的图像:

    function loadImages(sources, callback) {
        var assetDir = 'http://kinlibtst.elitno.net/PROJECT/';
        var images = {};
        var loadedImages = 0;
        var numImages = 0;
        for (var src in sources) {
            numImages++;
        }
        for (var src in sources) {
            images[src] = new Image();
            images[src].onload = function() {
                if (++loadedImages >= numImages) {
                    callback(images);
                }
            };
            images[src].src = assetDir + sources[src];
        }
    }
    
    function initStage(images) {
        var stage = new Kinetic.Stage({
            container: 'container',
            width: 900,
            height: 1000
        });
    
        var imagesLayer = new Kinetic.Layer();
    
        // img vars
        var n_amer = new Kinetic.Image({
            image: images.n_amer,
            x: 0,
            y: 0
        });
    
        // mouse events
        n_amer.on('mouseover', function() {
            this.setImage(images.n_amer_sel);
            stage.draw();
        });
        n_amer.on('mouseout', function() {
            this.setImage(images.n_amer);
            stage.draw();
        });
    
        // imageBuffer for transparent pixels
        n_amer.createImageBuffer(function() {
            imagesLayer.drawBuffer();
        });
    
        // add to stage
        imagesLayer.add(n_amer);
        stage.add(imagesLayer);
    }
    
    window.onload = function() {
        var sources = {
            n_amer: 'N-Amer.png',
            n_amer_sel: 'N-Amer_sel.png'
        };
        loadImages(sources, initStage);
    };​
    

    【讨论】:

    • 最终,你的想法最终是最好的 :) 但是有一个透明度错误(createImageBuffer()),但幸运的是它不会破坏任何东西。谢谢!
    【解决方案2】:

    尝试在未选中的图像上添加两个处理程序,例如:

    n_amer.on('mouseover', function() {
        imagesLayer.add(n_amer_sel)
        stage.draw();
    });
    n_amer.on('mouseout', function() {  
        imagesLayer.remove(n_amer_sel);
        stage.draw();
    });
    

    【讨论】:

    • 切换到显示/隐藏而不是像其他响应者提到的那样添加/删除可能仍然是一个好主意。
    【解决方案3】:

    这是一个非常奇怪的行为...可能与图像缓冲区有关...您可以尝试在侦听器中重绘缓冲区。

    无论如何,我建议添加这两个图像并使用show()hide()。此操作通常比添加/删除子节点更快。

    var n_amer_sel = new Kinetic.Image({
        image: images.n_amer_sel,
        x: 0,
        y: 0,
        visible: false
    });
    
    n_amer.on('mouseover', function() {
        n_amer_sel.show();
        stage.draw();
    });
    n_amer_sel.on('mouseout', function() {  
        n_amer_sel.hide();
        stage.draw();
    });
    
    // add to stage
    imagesLayer.add(n_amer);
    imagesLayer.add(n_amer_sel);
    stage.add(imagesLayer);
    

    您可以在fiddle 中看到它的工作原理(除了受污染的画布问题)

    【讨论】: