如何使一个橡皮擦与kineticjs 5.1.0作用于多层? [英] How to make an eraser with kineticjs 5.1.0 acting on multi-layer?

查看:142
本文介绍了如何使一个橡皮擦与kineticjs 5.1.0作用于多层?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



橡皮擦需要在多层上有效(layerA,layerB在我的代码中)。我想用橡皮擦与kineticjs,但我有一些问题。和一个简单的按钮或一些复选框我可以选择橡皮擦是否将工作在第一或第二层,为什么不是所有的。



她是一个jsfiddle,显示我已解释:



http://jsfiddle.net/junkees/jA2V8/2/

  var stage = new Kinetic.Stage({
container:'container',
width:400,
height :500
});
var layerA = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function(){
var x = new Kinetic.Image({
x:0,
y:0,
image:imageObj,
draggable:false
});

//将形状添加到图层
layerA.setListening(false);
layerA.add(x);


//将图层添加到舞台
stage.add(layerA);
layerA.setZIndex(10);
//layerA.draw();
};
imageObj.src =https://imagizer.imageshack.us/v2/595x397q90/707/u8q3.jpg

var layerB = new Kinetic.Layer();
var imagj = new Image();
imagj.onload = function(){
var x = new Kinetic.Image({
x:0,
y:0,
image:imagj,
});

//将形状添加到图层
layerB.setDraggable(true);
layerB.setListening(true);
layerB.add(x);


//将层添加到阶段
stage.add(layerB);
layerB.setZIndex(100);

layerB.draw();
};
imagj.src ='http://jsfiddle.net/img/initializing.png';

我可以擦除青蛙(或其他层)一部分的咖啡(第二层)用我的老鼠,一个圆圈(半径不要紧,我会使一个jquery滑块来定义它的大小;))



我使用的是最新版本的kineticjs,5.1.0



对不起对于这个问题的所有上一篇文章,我读过他们,但他们没有为我工作,因为版本。我已经搜索无处不在google让我搜索,没有找到可以帮助我,所以我问她的问题



这里我发现一些部分工作:



http://jsfiddle.net/ junkees / jA2V8 / 3 /



在这一个中,我创建了一个新的形状并将其附加到图层,因为形状和图像都是在同一层,图层是可拖动的,所以它会拖动他们,就像你可以看到,但它只是我想要的微型部分:/



我编辑我的代码和她我可以说一点点我会成功做到!
她的新jsfiddle: http://jsfiddle.net/junkees/jA2V8/5/
和她的一些问题:




  • 即使我设置了目的地,



我是以正确的方式完成此操作吗?

解决方案

globalCompositeOperation 用于使用新绘图(例如您的圆形拖动鼠标)来擦除现有的画布像素。



KineticJS尚不太适合创建橡皮擦工具。这是因为它还不支持 globalCompositeOperation



一个解决方法是创建一个Kinetic.Shape对象



然后,使用Kinetic.Shape时,您将获得对本地画布上下文的引用:

  var ctx = yourLayer.getContext()._ context; 

使用这个本地画布上下文,您可以使用 globalCompositeOperation 将自定义形状变成橡皮擦。

  ctx.globalCompositeOperation ='destination-out'; 

//现在任何新图形都将会删除现有像素



这里是一个演示: http://jsfiddle.net/m1erickson/tf7m3/




  • 图片的左边25%是底层(显示原始图片)

  • 接下来的25%显示中间图层(不透明度为50% / li>
  • 接下来的25%显示中间层&

  • 最后25%显示顶层(再次是蓝色矩形,50%不透明度)



圆圈在动作中显示中间层和顶层的Kinetic.Shape橡皮擦。他们使用目的地输出合成来擦除中间和左边的红色和蓝色矩形,顶层。结果是底层通过已删除圈子显示。





示例代码:

 <!DOCTYPE html> 
< html>
< head>
< meta charset =utf-8>
< title> Prototype< / title>
< script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>
< script src =http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js>< / script>
< style>
body {padding:20px;}
#container {
border:solid 1px #ccc;
margin-top:10px;
width:350px;
height:219px;
}
< / style>
< script>
$(function(){

var stage = new Kinetic.Stage({
container:'container',
width:350,
height :219
});
var bottomlayer = new Kinetic.Layer();
stage.add(bottomlayer);
var middlelayer = new Kinetic.Layer $ b stage.add(middlelayer);
var toplayer = new Kinetic.Layer();
stage.add(toplayer);

var sw = stage.width ;
var sh = stage.height();
var cutout = [];
var PI2 = Math.PI * 2;

var img = new Image ();
img.onload = start;
img.src =https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg;
function start ){
var kImage = new Kinetic.Image({
image:img,
});
bottomlayer.add(kImage);
bottomlayer.draw ;
middlelayer.draw();
toplayer.draw();
};

var midRed = new Kinetic.Rect({
x:sw /4,y:0,width:stage.width()/ 2,height:stage.height(),
fill:red,
opacity:0.50
});
middlelayer.add(midRed);

var middleEraser = new Kinetic.Shape({
x:0,y:0,
fill:blue,
drawFunc:function b $ b var ctx = middlelayer.getContext()._ context;
ctx.save();
ctx.globalCompositeOperation =destination-out;
ctx.beginPath();
for(var i = 0; i var cut = cutout [i];
ctx.arc(cut.x,cut.y,15,0, PI2);
ctx.closePath();
}
ctx.fill();
ctx.restore();
}
});
middlelayer.add(middleEraser);



var topBlue = new Kinetic.Rect({
x:stage.width()/ 2,y:0,width:stage.width 2,height:stage.height(),
fill:blue,
opacity:0.50
});
toplayer.add(topBlue);
toplayer.draw();

var topEraser = new Kinetic.Shape({
x:0,y:0,
fill:blue,
drawFunc:function(context){
var ctx = toplayer.getContext()._ context;
ctx.save();
ctx.globalCompositeOperation =destination-out;
ctx.beginPath();
for(var i = 0; i var cut = cutout [i];
ctx.arc(cut.x,cut.y,15,0, PI2);
ctx.closePath();
}
ctx.fill();
ctx.restore();
}
});
toplayer.add(topEraser);

stage.on('contentClick',function(){
var pos = stage.getPointerPosition();
var mouseX = parseInt(pos.x);
var mouseY = parseInt(pos.y);
cutoututs.push({x:mouseX,y:mouseY});
middlelayer.draw();
toplayer.draw
});

}); // end $(function(){});

< / script>
< / head>
< body>
< h4>点击删除顶部2层&显示底部图片< / h4>
< div id =container>< / div>
< / body>
< / html>


I want to make an eraser with kineticjs, but i have some problem.

The eraser need to be efficient on multiple layer (layerA, layerB in my code) and with a simple button or some check box I can choose if the eraser will work on the first or second layer, and why not on all of them. I also need to keep them draggable.

her is a jsfiddle that show what I've explained:

http://jsfiddle.net/junkees/jA2V8/2/

     var stage = new Kinetic.Stage({
    container: 'container',
    width: 400,
    height: 500
});
var layerA = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
  var x = new Kinetic.Image({
    x: 0,
    y: 0,
    image: imageObj,    
    draggable:false
  });

  // add the shape to the layer
  layerA.setListening(false);
  layerA.add(x);


  // add the layer to the stage
  stage.add(layerA);
  layerA.setZIndex(10);
  //layerA.draw();
};
imageObj.src="https://imagizer.imageshack.us/v2/595x397q90/707/u8q3.jpg"

var layerB = new Kinetic.Layer();
var imagj = new Image();
imagj.onload = function() {
  var x = new Kinetic.Image({
    x: 0,
    y: 0,
    image: imagj,
  });

  // add the shape to the layer
  layerB.setDraggable(true);
  layerB.setListening(true);
  layerB.add(x);


  // add the layer to the stage
  stage.add(layerB);
  layerB.setZIndex(100);

  layerB.draw();
};
imagj.src = 'http://jsfiddle.net/img/initializing.png';

i whant to be able to erase the frog (or something other of her layer) and to erase a part of the cup of coffee(second layer) with my mouse, with a circle (the radius doesn't matter, i'll make a jquery slider to define it's size ;) )

I'm using the latest version of kineticjs, the 5.1.0

sorry for all the previous post about this question, I've read them but them didn't work for me because of the version. I've already search everywhere google let me search and didn't found something that can help me so I ask her my question

Here I've found something that partially works:

http://jsfiddle.net/junkees/jA2V8/3/

In this one I've created a new shape and attach it to the layer, because the shape and the image are both in the same layer and the layer is draggable so it'll drag both of them like you can see but it's just a micro part of what I want :/

I've edited my code and her I can say little by little i'll success to do it! her the new jsfiddle: http://jsfiddle.net/junkees/jA2V8/5/ and her some problem:

  • even if i've set the destination out I can't erase, juste write
  • I really don't see how to proceed when i whant to stop to "erase"

Am I in the right way to finish this?

解决方案

globalCompositeOperation is used to "erase" existing canvas pixels using new drawings (like your circle-dragged-with-mouse).

KineticJS is not yet well suited to creating an "eraser" tool. That's because it doesn't yet support globalCompositeOperation.

A workaround is to create a Kinetic.Shape object which lets you draw with native canvas commands.

Then you get a reference to a native canvas context while using a Kinetic.Shape like this:

var ctx=yourLayer.getContext()._context;

With this native canvas context you can use globalCompositeOperation to turn the custom shape into an eraser.

ctx.globalCompositeOperation='destination-out';

// now any new drawings will erase existing pixels

You will need to have a Kinetic.Shape "eraser" on every layer that you want to penetrate with the erasings.

Here is a Demo: http://jsfiddle.net/m1erickson/tf7m3/

  • The left 25% of the image is the bottom layer (showing the original image)
  • The next 25% shows the middle layer (a red rect at 50% opacity)
  • The next 25% shows both the middle layer & top layer (top=a blue rect at 50% opacity)
  • The last 25% shows the top layer (again, the blue rect at 50% opacity)

The circles show the Kinetic.Shape erasers on both the middle and top layers in action. They use 'destination-out' compositing to erase the red and blue rectangles on the middle & top layers. The result is that the bottom layer shows through the "erased" circles.

Example code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Prototype</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:350px;
  height:219px;
}
</style>        
<script>
$(function(){

    var stage = new Kinetic.Stage({
        container: 'container',
        width: 350,
        height: 219
    });
    var bottomlayer = new Kinetic.Layer();
    stage.add(bottomlayer);
    var middlelayer = new Kinetic.Layer();
    stage.add(middlelayer);
    var toplayer = new Kinetic.Layer();
    stage.add(toplayer);

    var sw=stage.width();
    var sh=stage.height();
    var cutouts=[];
    var PI2=Math.PI*2;

    var img=new Image();
    img.onload=start;
    img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
    function start(){
        var kImage=new Kinetic.Image({
            image:img,
        });
        bottomlayer.add(kImage);
        bottomlayer.draw();
        middlelayer.draw();
        toplayer.draw();
    };

    var midRed=new Kinetic.Rect({
        x:sw/4,y:0,width:stage.width()/2,height:stage.height(),
        fill:"red",
        opacity:0.50
    });
    middlelayer.add(midRed);

    var middleEraser=new Kinetic.Shape({
      x:0,y:0,
      fill:"blue",
      drawFunc: function(context) {
        var ctx=middlelayer.getContext()._context;
        ctx.save();
        ctx.globalCompositeOperation="destination-out";
        ctx.beginPath();
        for(var i=0;i<cutouts.length;i++){
            var cut=cutouts[i];
            ctx.arc(cut.x,cut.y,15,0,PI2);
            ctx.closePath();
        }
        ctx.fill();
        ctx.restore();
      }
    });
    middlelayer.add(middleEraser);



    var topBlue=new Kinetic.Rect({
        x:stage.width()/2,y:0,width:stage.width()/2,height:stage.height(),
        fill:"blue",
        opacity:0.50
    });
    toplayer.add(topBlue);
    toplayer.draw();

    var topEraser=new Kinetic.Shape({
      x:0,y:0,
      fill:"blue",
      drawFunc: function(context) {
        var ctx=toplayer.getContext()._context;
        ctx.save();
        ctx.globalCompositeOperation="destination-out";
        ctx.beginPath();
        for(var i=0;i<cutouts.length;i++){
            var cut=cutouts[i];
            ctx.arc(cut.x,cut.y,15,0,PI2);
            ctx.closePath();
        }
        ctx.fill();
        ctx.restore();
      }
    });
    toplayer.add(topEraser);

    stage.on('contentClick',function(){
        var pos=stage.getPointerPosition();
        var mouseX=parseInt(pos.x);
        var mouseY=parseInt(pos.y);
        cutouts.push({x:mouseX,y:mouseY});
        middlelayer.draw();
        toplayer.draw();
    });

}); // end $(function(){});

</script>       
</head>
<body>
    <h4>Click to "erase" top 2 layers & reveal bottom image</h4>
    <div id="container"></div>
</body>
</html>

这篇关于如何使一个橡皮擦与kineticjs 5.1.0作用于多层?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆