I ran into an issue while using kineticJS to create multiple stages.
I am trying to export multiple "stages" to images but I cant get past exporting the first stage, the datatoURL function doesnt seem to be working, and it breaks my script, or perhaps I'm calling it at the wrong location...
When the user clicks the save button, each stage should be converted to an image and displayed on the same page.
Can anyone tell me why the first stage is not being displayed as an image on the page?
Thanks in advance
Here is the code that puts the stage data into the image placeholder on the page.
document.getElementById('save').addEventListener('click', function() {
stage.toDataURL({
callback: function(dataUrl) {
document.getElementById("canvasimg").src = dataUrl;
document.getElementById("canvasimg").style.display = "inline";
}
});
}, false);
below is the full code:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Canvas</title>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript' src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<script type='text/javascript'>
$(window).load(function(){
var highlightWidth = 8;
var stage = new Kinetic.Stage({
container: 'container1',
width: 300,
height: 100
});
var layer = new Kinetic.Layer();
stage.add(layer);
document.getElementById('save').addEventListener('click', function() {
stage.toDataURL({
callback: function(dataUrl) {
document.getElementById("canvasimg").src = dataUrl;
document.getElementById("canvasimg").style.display = "inline";
}
});
}, false);
var dropzone = new Kinetic.Stage({
container: 'container2',
width: 300,
height: 100
});
var dropLayer = new Kinetic.Layer();
dropzone.add(dropLayer);
addBackground(stage, layer, dropLayer);
layer.draw();
addBackground(dropzone, dropLayer, layer);
dropLayer.draw();
var stage2 = new Kinetic.Stage({
container: 'container3',
width: 300,
height: 100
});
var layer2 = new Kinetic.Layer();
stage2.add(layer2);
var dropzone2 = new Kinetic.Stage({
container: 'container4',
width: 300,
height: 100
});
var dropLayer2 = new Kinetic.Layer();
dropzone2.add(dropLayer2);
addBackground(stage2, layer2, dropLayer2);
layer2.draw();
addBackground(dropzone2, dropLayer2, layer2);
dropLayer2.draw();
var images = {};
var URLs = {
house1: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-3.jpg',
house2: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-4.jpg',
house3: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg'
};
loadImages(URLs, start);
function start() {
var house1 = kImage(images.house1, 10, 10, 50, 50, layer);
var house2 = kImage(images.house2, 75, 10, 50, 50, layer);
var house3 = kImage(images.house3, 140, 10, 50, 50, layer);
layer.draw();
var house1 = kImage(images.house1, 10, 10, 50, 50, dropLayer);
var house2 = kImage(images.house2, 75, 10, 50, 50, dropLayer);
var house3 = kImage(images.house3, 140, 10, 50, 50, dropLayer);
dropLayer.draw();
var house1 = kImage(images.house1, 10, 10, 50, 50, layer2);
var house2 = kImage(images.house2, 75, 10, 50, 50, layer2);
var house3 = kImage(images.house3, 140, 10, 50, 50, layer2);
layer.draw();
var house1 = kImage(images.house1, 10, 10, 50, 50, dropLayer2);
var house2 = kImage(images.house2, 75, 10, 50, 50, dropLayer2);
var house3 = kImage(images.house3, 140, 10, 50, 50, dropLayer2);
dropLayer.draw();
}
function swapStagesIfSelected(sourceLayer, destinationLayer, startX, startY) {
var elements = sourceLayer.get("Image");
var totalWidth = 0;
var maxHeight = -999;
var layerWidth = destinationLayer.getStage().getWidth();
var layerHeight = destinationLayer.getStage().getHeight();
for (var i = 0; i < elements.length; i++) {
if (elements[i].isSelected) {
totalWidth += elements[i].getWidth();
maxHeight = Math.max(elements[i].getHeight(), maxHeight);
}
}
if (startX + totalWidth > layerWidth) {
startX = layerWidth - totalWidth - 15;
}
if (startY + maxHeight > layerHeight) {
startY = layerHeight - maxHeight - 15;
}
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element.isSelected) {
var img = element.getImage();
kImage(img, startX, startY, element.getWidth(), element.getHeight(), destinationLayer);
startX += element.getWidth() + 10;
element.remove();
}
}
sourceLayer.draw();
destinationLayer.draw();
}
function kImage(image, x, y, width, height, theLayer) {
var image = new Kinetic.Image({
image: image,
x: x,
y: y,
width: width,
height: height,
strokeWidth: 0,
stroke: "white",
draggable: true
});
image.myLayer = theLayer;
image.isSelected = false;
image.on("click", function () {
this.myLayer.draw();
});
image.myLayer.add(image);
return (image);
}
function addBackground(theStage, theLayer, otherLayer) {
var background = new Kinetic.Rect({
x: 0,
y: 0,
width: theStage.getWidth(),
height: theStage.getHeight(),
fill: "white",
stroke: "blue",
strokeWidth: 1
});
background.on("click", function () {
var pos = theStage.getMousePosition();
var mouseX = parseInt(pos.x);
var mouseY = parseInt(pos.y);
swapStagesIfSelected(otherLayer, theLayer, mouseX, mouseY);
});
theLayer.add(background);
}
function loadImages(URLs, callback) {
var loaded = 0;
var needed = 0;
for (var url in URLs) {
needed++;
console.log(url);
}
for (var url in URLs) {
images[url] = new Image();
images[url].onload = function () {
if (++loaded >= needed) {
callback(images);
}
};
images[url].src = URLs[url];
}
}
});
</script>
</head>
<body>
<div id="container1"></div>
<div id="container2"></div>
<div id="container3"></div>
<div id="container4"></div>
<img style="background:url(test1.png);" id="canvasimg" style="display:none;">
<button id="save">Save as image</button>
</body>
</html>
Related
I'm using this code to display an openstreetmap. It works great on a desktop display but it's not very responsive friendly. I like to have a square sized map. I'm having some problems to find the right parameters for a responsive hight and width.
How can I set it to a 1:1 ratio?
My demo of the below source code: https://jsfiddle.net/uyn9posg/
<link id="cf7-map-field-leaflet-css" rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script id="cf7-map-field-leaflet-js" src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<div style="position:relative">
<div id="CF7MapFieldDiv" style="height:600px;width:100%"></div>
<span style="position:absolute;right:0px;bottom:20px;font: 12px Arial,Helvetica,sans-serif;background-color: rgba(255, 255, 255, 0.698);padding:2px 7px;z-index: 1000;" >
Marker bei: <span id="CF7MapMarkerAt">none</span>
</span>
</div>
<script>
var map;
var marker;
function updateMarkerPosition(e) {
//var markerLatLang = [e.lat.toFixed(6), e.lng.toFixed(6)].join(',');
var markerLong = e.lng.toFixed(6);
var markerLat = e.lat.toFixed(6);
//document.getElementById('CF7MapMarkerAt').innerHTML = markerLatLang;
document.getElementById('CF7MapMarkerAt').innerHTML = "Lat="+markerLat +", Long="+markerLong;
var hidd = document.getElementById('CF7MapLocationHidden');
var hidd2 = document.getElementById('CF7MapLocationHidden_long');
var hidd3 = document.getElementById('CF7MapLocationHidden_lat');
var hidd4 = document.getElementById('CF7MapLocationHidden_zoom');
//var val = [map.getZoom(), markerLatLang].join(';');
var zoomstufe = map.getZoom();
//if (!!hidd) { hidd.value = val; }
if (!!hidd2) { hidd2.value = markerLong; }
if (!!hidd3) { hidd3.value = markerLat; }
if (!!hidd4) { hidd4.value = zoomstufe; }
}
function onMarkerDrag(e) {
updateMarkerPosition(marker.getLatLng());
}
function onMapClick(e) {
map.removeLayer(initMarker);
if (marker === undefined) {
var markerIcon = L.icon({
iconUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-icon.png',
shadowUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-shadow.png',
iconSize: [25, 41],
shadowSize: [41, 41],
shadowAnchor: [15, 41]
});
marker = L.marker(e.latlng, {
icon: markerIcon,
draggable: true
}).addTo(map);
marker.on('drag', onMarkerDrag);
} else {
marker.setLatLng([e.latlng.lat, e.latlng.lng]);
}
updateMarkerPosition(e.latlng);
}
var initMarker = {};
function initmap() {
// set up the map
map = new L.Map('CF7MapFieldDiv');
// create the tile layer with correct attribution
var mapUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var mapAttrib = '© OpenStreetMap contributors';
var mapTile = new L.TileLayer(mapUrl, {
minZoom: 2,
maxZoom: 18,
attribution: mapAttrib
});
map.addLayer(mapTile);
// set default view (London)
//map.setView(new L.LatLng(51.501, -0.105), 8);
map.setView(new L.LatLng(47.77929097015571, 9.609822830498674), 9);
initMarker = L.marker([47.77929097015571, 9.609822830498674], {
iconUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-icon.png',
shadowUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-shadow.png',
iconSize: [25, 41],
shadowSize: [41, 41],
shadowAnchor: [15, 41], draggable: true
}).addTo(this.map);
// add events
map.on('click', onMapClick);
}
initmap();
</script>
Constraining to the Smallest Viewport Dimension
Not sure if this would be an alright way of doing for your use case. But I usually like to take the smaller (minimum) of the viewport height viewport width, min(100vh,100vw) and use that to set the height and width of the element I'm trying to keep a square 1:1 aspect ratio. This will also work for other fractions of viewport height and width. Effectively, this will contain the square to the smallest dimension. Press the blue Run code snippet button below to see the results and test the responsiveness using the full page link:
Minimal Example:
.Rectangle {
--Dimensions: min(80vh, 80vw);
height: var(--Dimensions);
width: var(--Dimensions);
position: absolute;
top: calc(50% - var(--Dimensions)/2);
left: calc(50% - var(--Dimensions)/2);
background-color: cyan;
}
<div class="Rectangle"></div>
Map Implementation:
<link id="cf7-map-field-leaflet-css" rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script id="cf7-map-field-leaflet-js" src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<div style="position:relative">
<div id="CF7MapFieldDiv" style="height:min(100vh,100vw); width:min(100vh,100vw); left: calc(50% - min(100vh,100vw)/2)"></div>
<span style="position:absolute;right:0px;bottom:20px;font: 12px Arial,Helvetica,sans-serif;background-color: rgba(255, 255, 255, 0.698);padding:2px 7px;z-index: 1000;" >
Marker bei: <span id="CF7MapMarkerAt">none</span>
</span>
</div>
<script>
var map;
var marker;
function updateMarkerPosition(e) {
//var markerLatLang = [e.lat.toFixed(6), e.lng.toFixed(6)].join(',');
var markerLong = e.lng.toFixed(6);
var markerLat = e.lat.toFixed(6);
//document.getElementById('CF7MapMarkerAt').innerHTML = markerLatLang;
document.getElementById('CF7MapMarkerAt').innerHTML = "Lat="+markerLat +", Long="+markerLong;
var hidd = document.getElementById('CF7MapLocationHidden');
var hidd2 = document.getElementById('CF7MapLocationHidden_long');
var hidd3 = document.getElementById('CF7MapLocationHidden_lat');
var hidd4 = document.getElementById('CF7MapLocationHidden_zoom');
//var val = [map.getZoom(), markerLatLang].join(';');
var zoomstufe = map.getZoom();
//if (!!hidd) { hidd.value = val; }
if (!!hidd2) { hidd2.value = markerLong; }
if (!!hidd3) { hidd3.value = markerLat; }
if (!!hidd4) { hidd4.value = zoomstufe; }
}
function onMarkerDrag(e) {
updateMarkerPosition(marker.getLatLng());
}
function onMapClick(e) {
map.removeLayer(initMarker);
if (marker === undefined) {
var markerIcon = L.icon({
iconUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-icon.png',
shadowUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-shadow.png',
iconSize: [25, 41],
shadowSize: [41, 41],
shadowAnchor: [15, 41]
});
marker = L.marker(e.latlng, {
icon: markerIcon,
draggable: true
}).addTo(map);
marker.on('drag', onMarkerDrag);
} else {
marker.setLatLng([e.latlng.lat, e.latlng.lng]);
}
updateMarkerPosition(e.latlng);
}
var initMarker = {};
function initmap() {
// set up the map
map = new L.Map('CF7MapFieldDiv');
// create the tile layer with correct attribution
var mapUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var mapAttrib = '© OpenStreetMap contributors';
var mapTile = new L.TileLayer(mapUrl, {
minZoom: 2,
maxZoom: 18,
attribution: mapAttrib
});
map.addLayer(mapTile);
// set default view (London)
//map.setView(new L.LatLng(51.501, -0.105), 8);
map.setView(new L.LatLng(47.77929097015571, 9.609822830498674), 9);
initMarker = L.marker([47.77929097015571, 9.609822830498674], {
iconUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-icon.png',
shadowUrl: 'http://cdn.leafletjs.com/leaflet-0.4.4/images/marker-shadow.png',
iconSize: [25, 41],
shadowSize: [41, 41],
shadowAnchor: [15, 41], draggable: true
}).addTo(this.map);
// add events
map.on('click', onMapClick);
}
initmap();
</script>
i'm using Kineticjs to make tools in canvas to resize it or rotate
but when i try to rotate it tool drag away of it and image have a wrong rotate
chick the link of my code
http://jsfiddle.net/vipmaa/qFmsM/3/
$(document).ready(function(){
function randomInt(min,max){
return Math.floor(Math.random()*(max-(min+1))+(min+1));
}
//try to use
var stage = new Kinetic.Stage({
container: 'stage',
width: 500,
height: 450,
offsetX:30,
offsetY:30
});
function update(activeAnchor) {
var group = activeAnchor.getParent();
var RotateSign = group.get('.RotateSign')[0];
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var mask = group.get('.mask')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'RotateSign':
var radius = mask.getWidth() * mask.getScale().x + 55;
group.rotate(radius);
break;
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
RotateSign.setY(anchorY);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
RotateSign.setX(anchorX);
break;
}
mask.setPosition(topLeft.getPosition());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if (width && height && (width > 1 && height > 1)) {
mask.setSize(width, height);
}
}
function addAnchor(group, x, y, name) {
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function () {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function () {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function () {
group.setDraggable(true);
layer.draw();
update(this);
});
// add hover styling
anchor.on('mouseover', function () {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function () {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
if(name == 'topLeft'){
anchor.hide();
}
}
function init(){
var rand = Math.ceil(Math.random() * 100087600);
var id = $(this).attr('data-name')+'_'+rand;
var config = {
id : 'canvas_'+id,
draggable:true,
name: 'art'
}
var x =randomInt(0,100);
var y =randomInt(0,100);
var artGroup = new Kinetic.Group({
x: x,
y: y,
name:'Group',
draggable: true
});
var layer = new Kinetic.Layer(config);
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: x,
y: y,
image: imageObj,
width: imageObj.width,
height: imageObj.height,
name: 'mask',
});
// add the shape to the layer
artGroup.add(yoda);
layer.add(artGroup);
// add the layer to the stage
stage.add(layer);
addAnchor(artGroup, x, y, 'topLeft');// it will be hide
addAnchor(artGroup, (x + imageObj.width), y, 'topRight');
addAnchor(artGroup, (x + imageObj.width), (y + imageObj.height), 'bottomRight');
addAnchor(artGroup, x, (y + imageObj.height), 'bottomLeft');
//Start add rotation tools
var sign = new Kinetic.Path({
name:'RotateSign',
x: x, y: y,
// Path from http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-path-tutorial/
data: 'M12.582,9.551C3.251,16.237,0.921,29.021,7.08,38.564l-2.36,1.689l4.893,2.262l4.893,2.262l-0.568-5.36l-0.567-5.359l-2.365,1.694c-4.657-7.375-2.83-17.185,4.352-22.33c7.451-5.338,17.817-3.625,23.156,3.824c5.337,7.449,3.625,17.813-3.821,23.152l2.857,3.988c9.617-6.893,11.827-20.277,4.935-29.896C35.591,4.87,22.204,2.658,12.582,9.551z',
scale: 0.4, fill: 'black',
offset:25,
dragOnTop: false,
draggable: true
});
sign.on('dragmove', function () {
update(this);
layer.draw();
});
sign.on('mousedown touchstart', function () {
//artGroup.setDraggable(false);
//this.moveToTop();
});
sign.on('dragend', function () {
//artGroup.setDraggable(true);
layer.draw();
update(this);
});
artGroup.add (sign);
//End add rotation tools
artGroup.on('dragstart', function () {
this.moveToTop();
});
artGroup.on('dragmove', function() {
var img = layer.get('.mask');
});
layer.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
layer.on('mouseout', function () {
document.body.style.cursor = 'default';
});
stage.draw();
};
imageObj.src = "http://www.w3schools.com/images/w3logotest2.png";
};
init();});
i want to rotate around image and tool stick in image
can you know what is wrong in the code
You can go through the below,
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var rotateAnchor = group.get('.rotateAnchor')[0];
var image = group.get('Image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();
// update anchor positions
switch (activeAnchor.getName()) {
case 'rotateAnchor':
break;
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
topRight.setX(anchorX);
bottomLeft.setY(anchorY);
break;
case 'bottomLeft':
topLeft.setX(anchorX);
bottomRight.setY(anchorY);
break;
}
if (topRight.getX() < topLeft.getX() + minImgSize) {
topRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getX() < topLeft.getX() + minImgSize) {
bottomRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getY() < topLeft.getY() + minImgSize) {
bottomRight.setY(topLeft.getY() + minImgSize);
}
if (bottomLeft.getY() < topLeft.getY() + minImgSize) {
bottomLeft.setY(topLeft.getY() + minImgSize);
}
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
image.setPosition({
x: topLeft.getPosition().x,
y: (topLeft.getPosition().y)
});
image.setWidth(width);
image.setHeight(height);
rotateAnchor.setX(width / 2 + topLeft.getX());
rotateAnchor.setY(height / 2 + topLeft.getY());
}
function addAnchor(group, x, y, name, dragBound) {
var stage = group.getStage();
var layer = group.getLayer();
var groupPos = group.getPosition();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 6,
//name: name,
id :"anchor",
name:name,
draggable: true,
dragOnTop: false
});
if (dragBound == 'rotate') {
startAngle = angle(groupPos.x, groupPos.y, x + groupPos.x, y + groupPos.y);
anchor.setAttrs({
dragBoundFunc: function (pos) {
return getRotatingAnchorBounds(pos, group);
}
});
}
anchor.on('dragmove', function () {
update(this);
stage.draw();
});
anchor.on('mousedown touchstart', function () {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function () {
group.setDraggable(true);
stage.draw();
});
// add hover styling
anchor.on('mouseover', function () {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
stage.draw();
});
anchor.on('mouseout', function () {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
stage.draw();
});
group.add(anchor);
}
function loadImages(sources, callback) {
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 = sources[src];
}
}
function radians(degrees) {
return degrees * (Math.PI / 180)
}
function degrees(radians) {
return radians * (180 / Math.PI)
}
function angle(cx, cy, px, py) {
var x = cx - px;
var y = cy - py;
return Math.atan2(-y, -x)
}
function distance(p1x, p1y, p2x, p2y) {
return Math.sqrt(Math.pow((p2x - p1x), 2) + Math.pow((p2y - p1y), 2))
}
function getRotatingAnchorBounds(pos, group) {
var groupPos = group.getPosition();
var rotation = degrees(angle(groupPos.x, groupPos.y, pos.x, pos.y) - startAngle);
var dis = distance(groupPos.x, groupPos.y, pos.x, pos.y);
console.log('x: ' + pos.x + '; y: ' + pos.y + '; rotation: ' + rotation + '; distance:' + dis);
group.setRotationDeg(rotation);
return pos;
}
function initStage(images) {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 400
});
var darthVaderGroup = new Kinetic.Group({
x: 270,
y: 100,
draggable: true
});
var yodaGroup = new Kinetic.Group({
x: 100,
y: 110,
draggable: true
});
var layer = new Kinetic.Layer();
/*
* go ahead and add the groups
* to the layer and the layer to the
* stage so that the groups have knowledge
* of its layer and stage
*/
layer.add(darthVaderGroup);
layer.add(yodaGroup);
stage.add(layer);
// darth vader
var darthVaderImg = new Kinetic.Image({
x: 0,
y: 0,
image: images.darthVader,
width: 200,
height: 138,
name: 'image'
});
darthVaderGroup.add(darthVaderImg);
addAnchor(darthVaderGroup, 0, 0, 'topLeft', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth(), 0, 'topRight', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth(), darthVaderImg.getHeight(), 'bottomRight', 'none');
addAnchor(darthVaderGroup, 0, darthVaderImg.getHeight(), 'bottomLeft', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth() / 2, darthVaderImg.getHeight() / 2, 'rotateAnchor', 'rotate');
darthVaderGroup.on('dragstart', function() {
this.moveToTop();
});
stage.draw();
}
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'
};
loadImages(sources, initStage);
Check http://jsfiddle.net/Qnil/XR7vL/
KineticJS is best to handle rotate image and stuff.
i found new canvas library (Fabric.js) it is solve all things i ask before
you can see blow link
Fabric JS
You can see different in rendering time
fabricjs vs kineticjs
I grabbed a working example of scaling and dragging an image from HTML5 Canvas Tutorials, but I want to achieve the same effect using rectangles.
When I adapt the code to use Rects, the anchors stop following the Rect. What's the secret to getting this working?
Thanks for any tips!
<!DOCTYPE HTML>
<html>
<head>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<style>
#container{
float:left;
border:1px solid red;
width:930px;
height:400px;
}
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body onmousedown="return false;">
<div id="container"></div>
<script>
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var mask = group.get('.mask')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
mask.setPosition(topLeft.getPosition());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if(width && height) {
mask.setSize(width, height);
}
}
function addAnchor(group, x, y, name) {
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function initStage() {
var stage = new Kinetic.Stage({
container: 'container',
width: 930,
height: 400
});
var redGroup = new Kinetic.Group({
x: 270,
y: 100,
draggable: true
});
var greenGroup = new Kinetic.Group({
x: 100,
y: 110,
draggable: true
});
var layer = new Kinetic.Layer();
layer.add(redGroup);
layer.add(greenGroup);
stage.add(layer);
// red
var redRect = new Kinetic.Rect({
x: 0,
y: 0,
name: 'mask',
width: 100,
height: 100,
fill: 'red',
stroke: 'black',
strokeWidth: 1,
opacity:0.5,
draggable:true
});
redGroup.add(redRect);
addAnchor(redGroup, 0, 0, 'topLeft');
addAnchor(redGroup, 100, 0, 'topRight');
addAnchor(redGroup, 100, 100, 'bottomRight');
addAnchor(redGroup, 0, 100, 'bottomLeft');
redGroup.on('dragstart', function() {
this.moveToTop();
});
// green
var greenRect = new Kinetic.Rect({
x: 0,
y: 0,
name: 'mask',
width: 100,
height: 100,
fill: 'green',
stroke: 'black',
strokeWidth: 1,
opacity:0.5,
draggable:true
});
greenGroup.add(greenRect);
addAnchor(greenGroup, 0, 0, 'topLeft');
addAnchor(greenGroup, 100, 0, 'topRight');
addAnchor(greenGroup, 100, 100, 'bottomRight');
addAnchor(greenGroup, 0, 100, 'bottomLeft');
greenGroup.on('dragstart', function() {
this.moveToTop();
});
stage.draw();
}
initStage();
</script>
</body>
</html>
becuase you making your rectangle as well draggable, just remove that and it works.
btw thanks for your solution i need something very similar. :)
here it is your working one:
<!DOCTYPE HTML>
<html>
<head>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<style>
#container {
float: left;
border: 1px solid red;
width: 930px;
height: 400px;
}
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body onmousedown="return false;">
<div id="container"></div>
<script>
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var mask = group.get('.mask')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
mask.setPosition(topLeft.getPosition());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if (width && height) {
mask.setSize(width, height);
}
}
function addAnchor(group, x, y, name) {
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function () {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function () {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function () {
group.setDraggable(true);
layer.draw();
update(this);
});
// add hover styling
anchor.on('mouseover', function () {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function () {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function initStage() {
var stage = new Kinetic.Stage({
container: 'container',
width: 930,
height: 400
});
var redGroup = new Kinetic.Group({
x: 270,
y: 100,
draggable: true
});
var greenGroup = new Kinetic.Group({
x: 100,
y: 110,
draggable: true
});
var layer = new Kinetic.Layer();
layer.add(redGroup);
layer.add(greenGroup);
stage.add(layer);
// red
var redRect = new Kinetic.Rect({
x: 0,
y: 0,
name: 'mask',
width: 100,
height: 100,
fill: 'red',
stroke: 'black',
strokeWidth: 1,
opacity: 0.5
});
redGroup.add(redRect);
addAnchor(redGroup, 0, 0, 'topLeft');
addAnchor(redGroup, 100, 0, 'topRight');
addAnchor(redGroup, 100, 100, 'bottomRight');
addAnchor(redGroup, 0, 100, 'bottomLeft');
redGroup.on('dragstart', function () {
this.moveToTop();
});
// green
var greenRect = new Kinetic.Rect({
x: 0,
y: 0,
name: 'mask',
width: 100,
height: 100,
fill: 'green',
stroke: 'black',
strokeWidth: 1,
opacity: 0.5
});
greenGroup.add(greenRect);
addAnchor(greenGroup, 0, 0, 'topLeft');
addAnchor(greenGroup, 100, 0, 'topRight');
addAnchor(greenGroup, 100, 100, 'bottomRight');
addAnchor(greenGroup, 0, 100, 'bottomLeft');
greenGroup.on('dragstart', function () {
this.moveToTop();
});
stage.draw();
}
initStage();
</script>
</body>
</html>
I am using Kinetic for some image processing. What happens is that I crop my image and then by clicking a button I want to make it black and white. For some reason the simple setFilter function is not working in this case, when you do crop first.
This is the code for cropping:
layer.removeChildren();
layer.clear();
image = new Kinetic.Image({
image: canvasImage,
x: (canvasWidth/2-theSelection.w/2),
y: (canvasHeight/2-theSelection.h/2),
width: theSelection.w,
height: theSelection.h,
crop: [theSelection.x, theSelection.y, theSelection.w, theSelection.h],
name: "image_tmp"
});
layer.add(image);
stage.draw();
And here is the function I decided to use for applying the filter:
var imgPixels = ctx.getImageData(xx, yy, imgW, imgH);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, xx, yy, 0, 0, imgPixels.width, imgPixels.height);
So now I get my cropped image with the filter, but if I want to continue doing something to the image object, I am getting:
TypeError: a.getType is not a function
I think also that the image object I used to use in my code, is now like undefined.
So for example I want after the filter to do layer.add(image) and I want image variable to be the new black and white one and not the old one.
So does anyone have an idea what is the problem, or how can I make the new imgPixels to be the same as my image. Thanks in advance
Is there any reason you didn't use the Kinetic.Filters.Grayscale filter?
Here are 2 ways you can do it:
1) Use setFilter (it works!)
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
crop: [0, 0, 50, 100]
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
2) Set the filter property on the image beforehand
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
crop: [0, 0, 50, 100],
filter: Kinetic.Filters.Grayscale
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
//yoda.setFilter(Kinetic.Filters.Grayscale);
//layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
Either way you don't need to add any new images, the original Kinetic.Image is filtered black & white.
UPDATE
Open this link: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/
And copy and paste this code, replacing all the code in the link. It's working fine for me..
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<button id="crop">Crop</button>
<button id="gray">Grayscale</button>
<button id="both">Both</button>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.0.min.js"></script>
<script defer="defer">
var yoda;
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
document.getElementById('crop').addEventListener('click', function() {
yoda.setCrop([20, 20, 50, 50]);
layer.draw();
});
document.getElementById('gray').addEventListener('click', function() {
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
});
document.getElementById('both').addEventListener('click', function() {
yoda.setCrop([20, 20, 50, 50]);
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
});
</script>
</body>
</html>
I am trying to combine drag and drop resize image and rotating image on touch, and mine is behaving strange http://jsfiddle.net/littlechad/Kuaxn/
My code is as follows:
function update (activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var stage = group.getStage();
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.setPosition(topLeft.getPosition());
var height = bottomLeft.attrs.y - topLeft.attrs.y;
var width = image.getWidth()*height/image.getHeight();
topRight.attrs.x = topLeft.attrs.x + width
topRight.attrs.y = topLeft.attrs.y;
bottomRight.attrs.x = topLeft.attrs.x + width;
bottomRight.attrs.y = topLeft.attrs.y + height;
if (width && height) {
image.setSize(width, height);
}
}
function rotate (activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var stage = group.getStage();
var pos = stage.getMousePosition();
var xd = 150 - pos.x ;
var yd = 150 - pos.y ;
var theta = Math.atan2(yd, xd);
var degree = theta / (Math.PI / 180) - 45;
var height = bottomLeft.attrs.y - topLeft.attrs.y;
var width = image.getWidth() * height / image.getHeight();
console.log(degree);
console.log(width);
console.log(height);
image.setRotationDeg(degree);
return {
x: image.getAbsolutePosition().x,
y: image.getAbsolutePosition().y
}
}
function addAnchor (group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: 'transparent',
strokeWidth: 0,
radius: 20,
name: name,
draggable: false,
dragOnTop: false
});
if(name === 'topRight'){
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 20,
name: name,
draggable: true,
dragOnTop: false
});
}
anchor.on('dragmove', function () {
update(this);
rotate(this);
layer.draw();
});
anchor.on('mousedown touchstart', function () {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function () {
group.setDraggable(true);
layer.draw();
});
group.add(anchor);
}
function initStage () {
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 800
});
var imageGroup = new Kinetic.Group({
x: 150,
y: 150,
draggable: true,
});
var layer = new Kinetic.Layer({
width: 128,
height: 128,
offset: [64, 64]
});
layer.add(imageGroup);
var imgObj = new Image();
var imageInstance = new Kinetic.Image({
x: 0,
y: 0,
image: imgObj,
width: 200,
height: 138,
name: 'image',
});
imgObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
imageGroup.add(imageInstance);
addAnchor(imageGroup, 0, 0, 'topLeft');
addAnchor(imageGroup, 200, 0, 'topRight');
addAnchor(imageGroup, 200, 138, 'bottomRight');
addAnchor(imageGroup, 0, 138, 'bottomLeft');
imageGroup.on('dragstart', function() {
update(this);
rotate(this);
this.moveToTop();
});
stage.add(layer);
stage.draw();
}
function writeMessage (messageLayer, message) {
var context = messageLayer.getContext();
messageLayer.clear();
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
//loadImages(sources, initStage);
initStage();
It seems that updating the offset is the problem, I have tried several things to set the offset so that it stays in the middle, yet I still can't figure out how, I am really new to HTML5 and KineticJs, please help me on this.
UPDATE:
The above fiddle is no longer working due to the fillColor broken on new browsers, I have updated the fiddle, although I haven't been able to figure out the solution for this.
Thanks
You were very close, just using some incorrect method names, and as was said before, the cdn needs to change.
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var stage = group.getStage();
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.setPosition(topLeft.getPosition());
var height = bottomLeft.attrs.y - topLeft.attrs.y;
var width = image.getWidth()*height/image.getHeight();
topRight.attrs.x = topLeft.attrs.x + width
topRight.attrs.y = topLeft.attrs.y;
bottomRight.attrs.x = topLeft.attrs.x + width;
bottomRight.attrs.y = topLeft.attrs.y + height;
if(width && height) {
image.setSize(width, height);
}
}
function rotate(activeAnchor){
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var stage = group.getStage();
var pos = stage.getPointerPosition();
var xd = 150 - pos.x ;
var yd = 150 - pos.y ;
var theta = Math.atan2(yd, xd);
var degree = theta / (Math.PI / 180) - 45;
var height = bottomLeft.attrs.y - topLeft.attrs.y;
var width = image.getWidth()*height/image.getHeight();
console.log(degree);
console.log(width);
console.log(height);
image.setRotationDeg(degree);
return {
x: image.getAbsolutePosition().x,
y: image.getAbsolutePosition().y
}
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#fff',
fill: '#fff',
strokeWidth: 2,
radius: 20,
name: name,
draggable: false,
dragOnTop: false
});
if(name === 'topRight'){
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 20,
name: name,
draggable: true,
dragOnTop: false
});
}
anchor.on('dragmove', function() {
update(this);
rotate(this);
layer.draw();
});
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
group.add(anchor);
}
function initStage() {
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 800
});
var imageGroup = new Kinetic.Group({
x: 150,
y: 150,
draggable: true,
});
var layer = new Kinetic.Layer({
width: 128,
height: 128,
offset: [64, 64]
});
layer.add(imageGroup);
var imgObj = new Image();
var imageInstance = new Kinetic.Image({
x: 0,
y: 0,
image: imgObj,
width: 200,
height: 138,
name: 'image',
});
imgObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-
vader.jpg';
imageGroup.add(imageInstance);
addAnchor(imageGroup, 0, 0, 'topLeft');
addAnchor(imageGroup, 200, 0, 'topRight');
addAnchor(imageGroup, 200, 138, 'bottomRight');
addAnchor(imageGroup, 0, 138, 'bottomLeft');
imageGroup.on('dragstart', function() {
update(this);
rotate(this);
this.moveToTop();
});
stage.add(layer);
stage.draw();
}
function writeMessage(messageLayer, message) {
var context = messageLayer.getContext();
messageLayer.clear();
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
loadImages(sources, initStage);
initStage();