creating overlay and removing parts of it on canvas using kineticjs - javascript

In a canvas painting application I want to add feature to create overlay over the whole canvas and then when I make a particular rectangle on the canvas the overlay should get removed from that region ,exactly like one on https://onpaste.com/ (select focus tool) . What I have thought is that if a rectangle is made on the canvas , then I can crop the current image and then paste the image on the canvas again over the overlay at the place which was selected . I am not sure , how to crop the image before pasting it on the canvas , I tried to use method setFillPaternImage of Kinetic.Image object ,but here I want to feed Kinetic.Image object instead of javascript image object because on Kinetic.Image object I can use setAttrs method .
Please tell how I can crop and add the image or if there is a better way to achieve the same . Link to fiddle -> http://jsfiddle.net/hearsid/9a2Hn/
<html>
<head>
<style>
</style>
</head>
<body>
<div id="container"></div>
<button id="button">this</button>
<script src="js/jquery.js"></script>
<script src="js/kinetic.js"></script>
<script>
var stage = new Kinetic.Stage({
container:'container',
width:500,
height:300
});
var layer=new Kinetic.Layer();
var img = new Image();
img.onload = function() {
imgObj = new Kinetic.Image({
x:0,y:0,width:400,height:300,image:img
});
layer.add(imgObj);
var circle = new Kinetic.Circle({
x:30,y:30,radius:30,fill:'red'
});
layer.add(circle);
var rect = new Kinetic.Rect({
x:0,y:0,width:300,height:500,fill:'gray',opacity:0.5
});
layer.add(rect);
stage.add(layer);
}
img.src="some.jpg";
$("#button").click(function() {
rect2 = new Kinetic.Rect({
x:200,y:30,width:100,height:100
});
/*
Careful with the commented area , here I wanted to crop the image before using FillPaternImage
var img2 = new Image();
img2.onload = function() {
imgObj2 = new Kinetic.Image({
image: img2 ,
x:300
});
imgObj2 = imgObj.clone();
imgObj2.setAttrs({image :img2 ,x:100 , y:0 });
*/
img2 = img ;
rect2.setFillPatternImage(img2);
layer.add(rect2);
layer.draw();
});
</script>
</body>
</html>

Your "clipped reveal" can be accomplished like this:
A Demo: http://jsfiddle.net/m1erickson/qXHAJ/
In a bottom layer:
Add an image.
Add a semi-transparent Rect to "frost" the bottom image.
In an overlay layer:
Add a group to a top overlay layer.
Set the clip property of the group to the area you want revealed.
In the group:
Add the image again (this second image will be "revealed" only in the groups clip area).
Add a draggable Rect to act as your "view"
(the Rect will have its X/Y/width/height set to the groups clip area.
When the user drags the Rect:
Change the group's clipping area to the Rect's X/Y.
The Rect will act as a draggable indicator of where the reveal should be.
The result is that the image is "frosted" everywhere except the draggable Rect.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/qXHAJ/
<!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-v4.7.2.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
var frostlayer=new Kinetic.Layer();
stage.add(layer);
stage.add(frostlayer);
var view;
var img=new Image();
img.onload=function(){
start();
}
//img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png";
img.src="KoolAidMan.png";
function start(){
var image=new Kinetic.Image({
image:img,
x:0,
y:0,
width:300,
height:300
});
layer.add(image);
var frost=new Kinetic.Rect({
x:0,
y:0,
width:300,
height:300,
fill:"white",
opacity:0.70
});
layer.add(frost);
var viewport=new Kinetic.Group({
x:0,
y:0,
width:300,
height:300,
clip:[30,30,100,100]
});
frostlayer.add(viewport);
unfrosted=new Kinetic.Image({
image:img,
x:0,
y:0,
width:300,
height:300
});
viewport.add(unfrosted);
view=new Kinetic.Rect({
x:30,
y:30,
width:100,
height:100,
strokeWidth:3,
stroke:"purple",
draggable:true
});
view.on("dragmove",function(){
viewport.setClip(this.getX(),this.getY(),100,100);
});
viewport.add(view);
layer.draw();
frostlayer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<h3>Drag the unfrosted Rect</h3>
<div id="container"></div>
</body>
</html>

Related

Display off on last polygon created with OpenLayers

With this example :
https://openlayers.org/en/latest/examples/draw-and-modify-features.html
I try to create a polygon but I want it to disappear when the polygon is complete.
Can someone help me ?
Thanks :)
Just remove the source when creating the interaction:
draw = new Draw({
type: 'Polygon'
});
When no destination source for the drawn features is set, the polygon will just disappear when completed (otherwise it is added to the source).
Listen to drawend event to get the polygon.
If I understand you correctly, you want to remove the draw interaction after the user geometry draw is complete. Like #Anatoly mention in the comments you can use the drawend event to remove the interactions.
Take a look at the example I made for you,
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.3.1/css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.3.1/build/ol.js"></script>
<title>End Draw Interaction After Draw</title>
</head>
<body>
<div>
<button id="startDraw">Start Draw</button>
<button id="endDraw">End Draw</button>
</div>
<div id="map" class="map"></div>
<script type="text/javascript">
// vector layer
var source = new ol.source.Vector();
var vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})
});
// map
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vector
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
// buttons
var startDrawBtn = document.getElementById('startDraw');
var endDrawBtn = document.getElementById('endDraw');
endDrawBtn.disabled = true;
// interaction
var draw = new ol.interaction.Draw({
source: source,
type: 'Polygon'
});
var snap = new ol.interaction.Snap({source: source});
function endInteractions() {
map.removeInteraction(draw);
map.removeInteraction(snap);
startDrawBtn.disabled = false;
endDrawBtn.disabled = true;
}
function startInteractions() {
startDrawBtn.disabled = true;
endDrawBtn.disabled = false;
map.addInteraction(draw);
map.addInteraction(snap);
draw.on('drawend', evt => {
// console.log(evt.feature);
endInteractions();
});
}
startDrawBtn.addEventListener('click', startInteractions);
endDrawBtn.addEventListener('click', endInteractions);
</script>
</body>
</html>

KineticJS - basic javascript scope issue

Ok, I'm trying to put the javascript in a separate source file. This is a newbie question, but I'm getting an 'undefined' error on layer.add(imageObj).
I'm guessing it's because of window.onLoad, but I didn't find an immediate answer.
<html>
<head>
<link rel="stylesheet" type="text/css" media="screen" href="index.css">
<script type="text/javascript" src="js/kinetic-v5.1.0.min.js"></script>
<script type="text/javascript" src="js/game.js" defer="defer"></script>
</head>
<body>
<div id="board"></div>
</body>
The javascript:
window.onload = function(){
var stage = new Kinetic.Stage({
container: 'board'
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var image = new Kinetic.Image({
x: 0,
y: 0,
image: imageObj,
width: 100,
height: 100
});
};
imageObj.src = 'resources/map.jpg';
layer.add(imageObj);
stage.add(layer);
};
You need to add into layer Kinetic.Image instance (image in your source) not imageObj. You can do this in onload function. See: http://jsbin.com/buroyi/2/edit

Selecting Kineticjs path by id

I am trying to create an interactive map and have been exploring with some of the prebuilt templates.
In this each country is created and highlights when the mouse is over them. My question is how would I go about making it highlight another country such a Brazil when any country has a mouseover. Thus how do I go about selecting another object when a country is highlighted.
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<script src="http://riskmap.filkor.org/paths.js"></script>
<script src="http://riskmap.filkor.org/gameData.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 1920,
height: 1080
});
var mapLayer = new Kinetic.Layer({
y: 20,
scale: 1
});
var topLayer = new Kinetic.Layer({
y: 20,
scale: 1
});
/*
* loop through country data
*/
for(id in TerritoryNames) {
var path = new Kinetic.Path({
data: TerritoryPathData[id].path,
fill: '#eee',
stroke: '#555',
strokeWidth: 1,
id: id
});
path.on('mouseover', function() {
this.setFill('#111');
this.moveTo(topLayer);
topLayer.drawScene();
});
path.on('mouseout', function() {
this.setFill('#eee');
this.moveTo(mapLayer);
topLayer.draw();
});
mapLayer.add(path);
}
stage.add(mapLayer);
stage.add(topLayer);
</script>
At any time, you can get a reference to a country through its id using stage.find:
var Brazil = stage.find("#Brazil")[0];
Then use that reference to highlight Brazil.

Make kineticjs use existing canvas

I am attempting to use kinetic.js with an existing canvas. The problem is that the kinetic.js API requires that you specify the id of the container element and then kinetic.js creates a Kinetic.Stage (which creates and uses its own canvas).
For instance:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 239,
y: 75,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
// add the shape to the layer
layer.add(rect);
// add the layer to the stage
stage.add(layer);
</script>
I want to be able to use an existing canvas element with kinetic.js instead of it creating its own. Is this possible?
A similar question has been asked before, however it doesn't seem to provide a correct answer.
Any ideas? Thanks!
An html canvas is just a bunch of pixels.
You can convert those pixels into an image and then use that image as the source for a Kinetic.Image.
// create an image from the existing canvas
var canvas2Image=new Image();
canvas2Image.onload=function(){
// create a Kinetic.Image using that image
var kImage=new Kinetic.Image({
x:0,
y:0,
width:canvas2Image.width,
height:canvas2Image.height,
image:canvas2Image
});
}
canvas2Image.src=canvas.toDataURL();

Kinetic.js Can't Load image onto canvas

I have to be missing something simple. I have gone fairly line-by-line, but it just doesn't seem to work. I can't get the image to load.
var imageToCanvas = function(){
var stage = new Kinetic.Stage("imgarea", 250, 256);
var layer = new Kinetic.Layer();
var imageobj = new Image();
imageobj.onload = function(){
var img = new Kinetic.Image({
x: 10,
y: 10,
image: imageobj,
});
layer.add(img);
stage.add(layer);
};
imageobj.src = "/static/img/unit-test-image.png";
console.log(imageobj);
};
$(document).ready( function(){
imageToCanvas();
});
<canvas id="imgarea" width="250px" height="256px"></canvas>
the same code seems to work in another canvas app that I used Kinetc.js with. I just can't seem to figure out why this one isn't working.
The code also looks fairly similar to the tutorial as well: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/
It looks like you're not defining the stage properly.. When I tried your code above I got an error about the container not being defined.. Try this instead..
var stage = new Kinetic.Stage({
container: "imgarea",
width: 250,
height: 256
});

Categories

Resources