Below is a KonvaJS project where you can add stickers to an image. However, it has a fixed width and a fixed height.
Now because the sizes are fixed, it won't work with anything response, like a bootstrap modal.
Here is my attempt following a KonvaJS response guide, see here. and the guide here.
In my attempt, after I upload the image, my code can't get the new width of the modal as it returns 0, so it can't calculate it for the size of the canvas.
How can I make the canvas responsive?
function centreRectShape(shape) {
shape.x((stage.getWidth() - shape.getWidth()) / 2);
shape.y((stage.getHeight() - shape.getHeight()) / 2);
}
var stage = new Konva.Stage({
container: 'canvas-container',
width: 650,
height: 300
});
var layer = new Konva.Layer();
stage.add(layer);
var bgRect = new Konva.Rect({
width: stage.getWidth(),
height: stage.getHeight(),
fill: 'gold',
opacity: 0.1
});
layer.add(bgRect);
var uploadedImage = new Konva.Image({
draggable: false
});
layer.add(uploadedImage);
// make an object to keep things tidy - not strictly needed, just being tidy
function addSticker(imgUrl){
// make the sticker image object
var stickerObj = new Konva.Image({
x: 240,
y: 20,
width: 93,
height: 104,
name: 'sticker',
draggable: true
});
layer.add(stickerObj);
// make the sticker image loader html element
var stickerImage = new Image();
stickerImage.onload = function() {
stickerObj.image(stickerImage);
layer.draw();
};
stickerObj.on('transformstart', function(){
undoBefore = makeUndo(this);
})
stickerObj.on('transformend', function(){
var undoAfter = makeUndo(this);
addUndo(123, undoBefore, undoAfter)
})
// assigning the URL of the image starts the onload
stickerImage.src = imgUrl;
}
imgObj = new Image();
imgObj.onload = function() {
uploadedImage.image(imgObj);
var padding = 20;
var w = imgObj.width;
var h = imgObj.height;
var targetW = stage.getWidth() - (2 * padding);
var targetH = stage.getHeight() - (2 * padding);
var widthFit = targetW / w;
var heightFit = targetH / h;
var scale = (widthFit > heightFit) ? heightFit : widthFit;
w = parseInt(w * scale, 10);
h = parseInt(h * scale, 10);
uploadedImage.size({
width: w,
height: h
});
centreRectShape(uploadedImage);
layer.draw();
}
imgObj.src = 'https://images.pexels.com/photos/787961/pexels-photo-787961.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260';
$('.sticker').on('click', function() {
var theSticker = addSticker($(this).attr('src'));
toggle(true);
toggle(false);
});
var vis = false;
$('#toggler').on('click', function(){
toggle(vis);
})
function undoData(opts){
this.x = opts.x;
this.y = opts.y;
this.width = opts.w;
this.height = opts.h;
this.rotation = opts.r;
}
var undoBefore;
function makeUndo(shape){
return new undoData({x:shape.getX(), y: shape.getY(), w: shape.getWidth(), h: shape.getHeight(), r: shape.getRotation() })
}
var undoList = [];
function addUndo(shapeId, before, after){
undoList.push({id: shapeId, before: before, after: after});
console.log(undoList[undoList.length - 1])
}
function toggle(isVisible){
if (!isVisible){
var shapes = stage.find('.sticker');
shapes.each(function(shape) {
var imgRotator = new Konva.Transformer({
node: shape,
name: 'stickerTransformer',
keepRatio: true,
enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
});
layer.add(imgRotator);
})
vis = true;
}
else {
var shapes = stage.find('.stickerTransformer');
shapes.each(function(shape) {
shape.remove();
})
vis=false;
}
layer.draw();
$('#toggler').html((vis ? 'Toggle Off' : 'Toggle On'));
}
html,
* {
margin: 0;
padding: 0;
}
body {
background: #eee;
}
#image-editor {
background: #fff;
border-radius: 3px;
border: 1px solid #d8d8d8;
width: 650px;
margin: 0 auto;
margin-top: 20px;
box-shadow: 0 3px 5px rgba(0, 0, 0, .2);
}
.stickers {
padding: 10px 5px;
background: #eee;
}
.stickers>img {
margin-right: 10px;
}
<div id="image-editor">
<div id="canvas-container"></div>
<div class="stickers">
<img class="sticker" src="https://craftblock.me/koa/fb-upload-clone/stickers/sticker%20(1).png" alt="Sticker" width="62px">
</div>
</div>
<script src="https://unpkg.com/konva#2.4.1/konva.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
So let me try to explain the issue a bit more: Check out the live version of my attempt of making it responsive.
As you can see, after trying to load the image into the canvas, the modal pops up but the canvas fails to resize.
Here's the JS to that:
/**
* Image Editor
*/
var stageWidth = 1000;
var stageHeight = 1000;
var stage = new Konva.Stage({
container: 'canvas-container',
width: stageWidth,
height: stageHeight
});
var layer = new Konva.Layer();
stage.add(layer);
var bgRect = new Konva.Rect({
width: stage.getWidth(),
height: stage.getHeight(),
fill: 'gold',
opacity: 0.1
});
layer.add(bgRect);
var uploadedImage = new Konva.Image({
draggable: false
});
layer.add(uploadedImage);
imgObj.onload = function () {
uploadedImage.image(imgObj);
var padding = 20;
var w = imgObj.width;
var h = imgObj.height;
var targetW = stage.getWidth() - (2 * padding);
var targetH = stage.getHeight() - (2 * padding);
var widthFit = targetW / w;
var heightFit = targetH / h;
var scale = (widthFit > heightFit) ? heightFit : widthFit;
w = parseInt(w * scale, 10);
h = parseInt(h * scale, 10);
uploadedImage.size({
width: w,
height: h
});
centreRectShape(uploadedImage);
layer.draw();
}
$('.sticker').on('click', function () {
addSticker($(this).attr('src'));
});
fitStageIntoParentContainer();
window.addEventListener('resize', fitStageIntoParentContainer);
function centreRectShape(shape) {
shape.x((stage.getWidth() - shape.getWidth()) / 2);
shape.y((stage.getHeight() - shape.getHeight()) / 2);
}
function addSticker(imgUrl) {
var stickerObj = new Konva.Image({
x: 240,
y: 20,
width: 93,
height: 104,
draggable: true
});
var stickerImage = new Image();
stickerImage.onload = function () {
stickerObj.image(stickerImage);
centreRectShape(stickerObj);
layer.draw();
};
stickerImage.src = imgUrl;
layer.add(stickerObj);
addModifiers(stickerObj);
}
function addModifiers(obj) {
var imgRotator = new Konva.Transformer({
node: obj,
keepRatio: true,
enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
});
layer.add(imgRotator);
}
function fitStageIntoParentContainer() {
var container = document.querySelector("edit-image-modal");
// now we need to fit stage into parent
var containerWidth = container.offsetWidth;
// to do this we need to scale the stage
var scale = containerWidth / stageWidth;
stage.width(stageWidth * scale);
stage.height(stageHeight * scale);
stage.scale({
x: scale,
y: scale
});
stage.draw();
}
The technique you have used to listen for 'resize' on the page will work for the main window but likely not for the modal. You can confirm that by some simple console.log() output.
You need to use the bootstrap event on('show.bs.modal') to catch when the modal is shown, which is when you really want to fire the call to fitStageIntoParentContainer();
See this SO post for info. It is not a duplicate but covers the bootstrap modal event.
In case that question is erased, you should be heading for something like:
$('your_modal_element_selector').on('show.bs.modal', function () {
fitStageIntoParentContainer();
});
Related
I'm working on my own canvas drawer project, and just stuck in the zoom in/out function. In my project I'm using scale and translate to make the zoom, as I want to keep all the canvas and its elements in the center.
After sketching a little bit(not a math genius), I succeeded to draw out the following formula to use in the translate process, so the canvas will be kept in the middle of its view port after zooming: Old width and height / 2 - New width and height(which are old width and height multiply by scale step, which is 1.1 in my case) / 2.
Logically speaking, that should make it work. But after trying few times the zoom in and zoom out, I can clearly see that the canvas has a little offset and it's not being centered to the middle of the viewport(by viewport I mean the stroked square representing the canvas).
I took my code out of my project and put it in fiddle, right here:
https://jsfiddle.net/s82qambx/3/
index.html
<div id="letse-canvas-container">
<canvas id="letse-canvas" width="300px" height="300px"></canvas>
<canvas id="letse-upper-canvas" width="300px" height="300px"></canvas>
</div>
<div id="buttons">
<button id="zoomin">
Zoom-in
</button>
<button id="zoomout">
Zoom-out
</button>
</div>
main.js
const canvas = {
canvas: document.getElementById('letse-canvas'),
upperCanvas: document.getElementById('letse-upper-canvas')
};
canvas.canvas.ctx = canvas.canvas.getContext('2d');
canvas.upperCanvas.ctx = canvas.upperCanvas.getContext('2d');
const CANVAS_STATE = {
canvas: {
zoom: 1,
width: 300,
height: 300
}
}
const Elements = [
{
x: 20,
y: 20,
width: 30,
height: 40
},
{
x:170,
y:30,
width: 100,
height: 100
}
];
const button = {
zoomin: document.getElementById('zoomin'),
zoomout: document.getElementById('zoomout')
}
button.zoomin.addEventListener('click', (e) => {
canvasZoomIn(e, canvas);
});
button.zoomout.addEventListener('click', (e) => {
canvasZoomOut(e, canvas);
});
function canvasZoomIn(e, canvas) {
const zoomData = getZoomData('in');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, 300, 300);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, 300, 300);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function canvasZoomOut(e, canvas) {
const zoomData = getZoomData('out');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const scale = CANVAS_STATE.canvas.zoom * zoomStep;
const docWidth = CANVAS_STATE.canvas.width * zoomStep;
const docHeight = CANVAS_STATE.canvas.height * zoomStep;
const translateX = CANVAS_STATE.canvas.width / 2 - docWidth / 2;
const translateY = CANVAS_STATE.canvas.height / 2 - docHeight / 2;
console.log(zoomStep);
console.log(scale, 'check');
console.log(docWidth);
console.log(docHeight);
console.log(translateX, 'check');
console.log(translateY, 'check');
return {
zoomStep,
scale,
docWidth,
docHeight,
translateX,
translateY
};
}
main.css
#letse-canvas-container {
position: relative;
float: left;
}
#letse-canvas {
border: 1px solid rgb(0, 0, 0);
/* visibility: hidden; */
}
#letse-upper-canvas {
/* position: absolute; */
/* top: 0px; */
left: 0px;
border: 1px solid;
/* visibility: hidden; */
}
Can someone suggest a reason? What am I missing here?
OK! So I managed to derive the right formula after searching in the net and testing few options. I used:
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const oldZoom = CANVAS_STATE.canvas.zoom;
const newZoom = oldZoom * zoomStep;
const zoomDifference = newZoom - oldZoom;
const docWidth = CANVAS_STATE.canvas.width * newZoom;
const docHeight = CANVAS_STATE.canvas.height * newZoom;
const translateX = (-(canvas.canvas.width / 2 * zoomDifference / newZoom));
const translateY = (-(canvas.canvas.height / 2 * zoomDifference / newZoom));
http://jsfiddle.net/Darbicus/VBeGF/
I want to add a small puzzle to website
but the shown code in the fiddle is not taking for the whole image,its taking only small part of the image,can any one give the solution please
Here is the code
function drawImage(imageObj) {
var piecesArray=new Array();
var horizontalPieces = 3;
var verticalPieces = 3;
var imageWidth = imageObj.width;
var imageHeight = imageObj.height;
var pieceWidth = Math.round(imageWidth/horizontalPieces);
var pieceHeight = Math.round(imageHeight/verticalPieces);
var stage = new Kinetic.Stage({
container: "container",
width: window.innerWidth,
height: window.innerHeight
});
var layer = new Kinetic.Layer();
for(i=0;i<horizontalPieces;i++){
piecesArray[i]=new Array();
for(j=0;j<verticalPieces;j++){
piecesArray[i][j] = new Object();
piecesArray[i][j].right=Math.floor(Math.random()*2);
piecesArray[i][j].down=Math.floor(Math.random()*2);
if(j>0){
piecesArray[i][j].up=1-piecesArray[i][j-1].down;
}
if(i>0){
piecesArray[i][j].left=1-piecesArray[i-1][j].right;
}
piecesArray[i][j].shape=new Kinetic.Shape({
drawFunc: function(i,j,pieceWidth,pieceHeight,tileObj){
return function(canvas) {
var x8=Math.round(pieceWidth/8);
var y8=Math.round(pieceHeight/8);
var context = canvas.getContext();
context.beginPath();
context.moveTo(0,0);
if(j!=0){
context.lineTo(3*x8,0);
if(tileObj.up==1){
context.quadraticCurveTo(2*x8,-2*y8,4*x8,-2*y8);
context.quadraticCurveTo(6*x8,-2*y8,5*x8,0);
}
else{
context.quadraticCurveTo(2*x8,2*y8,4*x8,2*y8);
context.quadraticCurveTo(6*x8,2*y8,5*x8,0);
}
}
context.lineTo(8*x8,0);
if(i!=horizontalPieces-1){
context.lineTo(8*x8,3*y8);
if(tileObj.right==1){
context.quadraticCurveTo(10*x8,2*y8,10*x8,4*y8);
context.quadraticCurveTo(10*x8,6*y8,8*x8,5*y8);
}
else{
context.quadraticCurveTo(6*x8,2*y8,6*x8,4*y8);
context.quadraticCurveTo(6*x8,6*y8,8*x8,5*y8);
}
}
context.lineTo(8*x8,8*y8);
if(j!=verticalPieces-1){
context.lineTo(5*x8,8*y8);
if(tileObj.down==1){
context.quadraticCurveTo(6*x8,10*y8,4*x8,10*y8);
context.quadraticCurveTo(2*x8,10*y8,3*x8,8*y8);
}
else{
context.quadraticCurveTo(6*x8,6*y8,4*x8,6*y8);
context.quadraticCurveTo(2*x8,6*y8,3*x8,8*y8);
}
}
context.lineTo(0,8*y8);
if(i!=0){
context.lineTo(0,5*y8);
if(tileObj.left==1){
context.quadraticCurveTo(-2*x8,6*y8,-2*x8,4*y8);
context.quadraticCurveTo(-2*x8,2*y8,0,3*y8);
}
else{
context.quadraticCurveTo(2*x8,6*y8,2*x8,4*y8);
context.quadraticCurveTo(2*x8,2*y8,0,3*y8);
}
}
context.lineTo(0,0);
canvas.fillStroke(this);
}
}(i,j,pieceWidth,pieceHeight,piecesArray[i][j]),
fillPatternImage:imageObj,
x:-pieceWidth*i,
y:-pieceHeight*j,
stroke: "#000000",
strokeWidth: 4,
lineCap: "round",
rotation : Math.PI * 0.5 * Math.floor(Math.random() * 4),
draggable: true,
offset: [pieceWidth/2,pieceHeight/2],
x: pieceWidth*i+pieceWidth/2 + (Math.random()*2)*((stage.getWidth()+pieceWidth)/20),
y: pieceHeight*j+pieceHeight/2 + (Math.random()*2)*((stage.getHeight()+pieceHeight)/20),
});
piecesArray[i][j].shape.on("mousedown", function(){
this.moveToTop();
});
piecesArray[i][j].shape.on("click", function(){
this.moveToTop();
this.rotateDeg(90)
layer.draw();
});
layer.add(piecesArray[i][j].shape);
}
}
stage.add(layer);
}
var jigsaw = function() {
var imageObj = new Image();
imageObj.src = "https://dl.dropboxusercontent.com/s/n9wrfvy9h4p5ufs/kidwallpaper.jpg";
imageObj.onload = function () {
drawImage(this);
}
}
jigsaw();
I am new in Fabric js. can anyone suggest me for restrict scale object within bounding box ?
my java-script code is below
(function(global) {
var canvas = new fabric.Canvas('maincanvas');
var yourNameObjs = [];
var goodtop =358, goodleft=250, boundingObject;
var boundingObject = new fabric.Rect({
left: 100,
top: 90,
width: 200,
height: 250,
opacity: 4,
selectable:false,
fill: 'red',
});
canvas.add(boundingObject);
addText = function(){
var nametoprint = $("#nametoprint").val();
canvas.remove(yourNameObjs);
yourNameObjs = new fabric.Text(nametoprint, {
left: 150, //Take the block's position
opacity: 9,
top: 150,
fontFamily: 'Delicious_500',
}
);
canvas.add(yourNameObjs);
canvas.on("object:moving", function(){
var obj = yourNameObjs;
var bounds = boundingObject;
obj.setCoords();
if(!obj.isContainedWithinObject(bounds)){
obj.setTop(goodtop);
obj.setLeft(goodleft);
} else {
goodtop = obj.top;
goodleft = obj.left;
}
});
canvas.on("object:scaling", function(){
var obj = yourNameObjs;
var bounds = boundingObject;
obj.setCoords();
if(!obj.isContainedWithinObject(bounds)){
obj.setTop(goodtop);
obj.setLeft(goodleft);
} else {
goodtop = obj.top;
goodleft = obj.left;
}
});
canvas.renderAll();
};
})();
html code is below
<input type="text" name="nametoprint" id="nametoprint" value="alex" />
<input type= "button" name="addtxt" id="addtxt" onclick="addText()" value="add text" />
<canvas id="maincanvas" style="border:1px solid #000;" width="400" height="450" ></canvas>
also i added this in fiddle here http://jsfiddle.net/pfgm8myp/
i want only allow to scale text object within the red bound box.moving object is working fine.i also added code for scaling but its not working.
can any one suggest me how to restrict this scaling ?
thanks in advance.
i posted it here with my own logic. http://jsfiddle.net/9xojfmyt/
i added below javascript code
(function(global) {
var canvas = new fabric.Canvas('maincanvas');
var yourNameObjs = [];
var goodtop =358, goodleft=250, boundingObject;
var boundingObject = new fabric.Rect({
left: 100,
top: 90,
width: 200,
height: 250,
opacity: 4,
selectable:false,
fill: 'red',
});
canvas.add(boundingObject);
addText = function(){
var nametoprint = $("#nametoprint").val();
canvas.remove(yourNameObjs);
yourNameObjs = new fabric.Text(nametoprint, {
left: 150, //Take the block's position
opacity: 9,
top: 150,
fontFamily: 'Delicious_500',
}
);
canvas.add(yourNameObjs);
// canvas moving limit
canvas.observe("object:moving", function(e){
var obj = yourNameObjs;
var bounds = boundingObject;
var objw = parseInt(parseInt(obj.width) * obj.scaleX);
var objh = parseInt(parseInt(obj.height) * obj.scaleY);
//left
if(obj.left < bounds.left){
obj.setLeft(bounds.left);
}
//top
if(obj.top < bounds.top){
obj.setTop(bounds.top);
}
//right
if((parseInt(obj.left) + objw) > (parseInt(bounds.left)+parseInt(bounds.width))){
obj.setLeft(((parseInt(bounds.left)+parseInt(bounds.width)) - objw));
}
//bottom
if((parseInt(obj.top) + objh) > (parseInt(bounds.top)+parseInt(bounds.height))){
obj.setTop(((parseInt(bounds.top)+parseInt(bounds.height)) - objh));
}
});
// canvas scaling limit
canvas.observe("object:scaling", function(e){
var obj = yourNameObjs;
var bounds = boundingObject;
var objw = parseInt(parseInt(obj.width) * obj.scaleX);
var objh = parseInt(parseInt(obj.height) * obj.scaleY);
//left
if(obj.left < bounds.left || (parseInt(obj.left) + objw) > (parseInt(bounds.left)+parseInt(bounds.width))){
obj.setLeft(bounds.left);
obj.setScaleX((bounds.width/obj.width));
}
//top
if(obj.top < bounds.top || (parseInt(obj.top) + objh) > (parseInt(bounds.top)+parseInt(bounds.height))){
obj.setTop(bounds.top);
obj.setScaleY((bounds.height/obj.height));
}
});
canvas.renderAll();
};
})();
Bit modification compare to Albert's answer. If you want to restrict object within canvas then replace moving event with below code.
// canvas scaling limit
canvas.observe("object:scaling", function(e){
var obj = e.target;
var bounds = {
left : 5, //here it keep 5 px margin from all direction
top : 5,
width : canvas.width - 10,
height : canvas.height - 10
};
var objw = parseInt(parseInt(obj.width) * obj.scaleX);
var objh = parseInt(parseInt(obj.height) * obj.scaleY);
//left
if(obj.left < bounds.left || (parseInt(obj.left) + objw) > (parseInt(bounds.left)+parseInt(bounds.width))){
obj.setLeft(bounds.left);
obj.setScaleX((bounds.width/obj.width));
}
//top
if(obj.top < bounds.top || (parseInt(obj.top) + objh) > (parseInt(bounds.top)+parseInt(bounds.height))){
obj.setTop(bounds.top);
obj.setScaleY((bounds.height/obj.height));
}
});
I am developing canvas to create hotel floor view. I am drawing images on canvas from database. I am taking x,y co-ordinates from database and drawing image on that points. But i want to give touch event to those images. I want to replace image on touch or click event. I want to create same functionality as that of book my show .
this is my code.
<!DOCTYPE HTML>
<html>
<head>
<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>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:100%;
height:100%;
}
html,body,kineticjs-content {
width:100%;
height:100%;
margin: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://localhost/zoilo_admin/public/kinetic-v5.1.0.js"></script>
<script defer="defer">
function writeMessage(message) {
text.setText(message);
layer.draw();
}
function loadImages(sources, position, callback) {
var assetDir = '';
var images = {};
var loadedImages = 0;
var numImages = 0;
for (i = 0; i < sources.length; i++)
{
numImages++;
}
for (i = 0; i < sources.length; i++)
{
images[i] = new Image();
images[i].onload = function () {
if (loadedImages == (sources.length - 1)) {
callback(images, position);
}
loadedImages++;
};
images[i].src = assetDir + sources[i];
}
}
function buildStage(images, position) {
var positionIndex = 0;
var tableActual = {};
console.log(images);
for (var i = 0; i < sources.length; i++)
{
console.log("Here");
tableActual[i] = new Kinetic.Image({
image: images[i],
x: position[i].x,
y: position[i].y
});
// var tableName = src;
// var table1 = new Kinetic.Image({
// image: images[src],
// x: position[positionIndex].x,
// y: position[positionIndex].y
// });
tableActual[i].on('click', function () {
console.log(this.index);
var image = new Kinetic.Image({
image: '4top.png',
x: position[this.index].x,
y: position[this.index].y
});
drawImage(image);
switch (this.index)
{
case 0:
writeMessage('Click on Table ' + 0);
tableActual[positionIndex] = new Kinetic.Image({
image: images[positionIndex],
x: position[positionIndex].x,
y: position[positionIndex].y
});
this.setIm = "4top.png";
break;
case 1:
writeMessage('Click on Table ' + 1);
break;
case 2:
writeMessage('Click on Table ' + 2);
break;
case 3:
writeMessage('Click on Table ' + 3);
break;
case 4:
writeMessage('Click on Table ' + 4);
break;
}
writeMessage('mouseover ' + this[src]);
});
drawImage(tableActual[i]);
positionIndex++;
}
// finally, we need to redraw the layer hit graph
layer.drawHit();
}
var stage = new Kinetic.Stage({
container: 'container',
width: $(window).width(),
height: $(window).height()
});
var layer = new Kinetic.Layer();
var text = new Kinetic.Text({
x: 10,
y: 10,
fontFamily: 'Calibri',
fontSize: 24,
text: '',
fill: 'black'
});
var sources = [
'house204-2.jpg',
'house204-1.jpg',
'4top.png',
'house204-1.jpg',
'4top.png'
];
var position = [
{
x: 380,
y: 60
},
{
x: 180,
y: 60
}
,
{
x: 90,
y: 60
},
{
x: 260,
y: 60
},
{
x: 50,
y: 60
}
];
loadImages(sources, position, buildStage);
function drawImage(Image)
{
layer.add(Image);
layer.add(text);
stage.add(layer);
// in order to ignore transparent pixels in an image when detecting
// events, we first need to cache the image
Image.cache();
// next, we need to redraw the hit graph using the cached image
Image.drawHitFromCache();
}
</script>
</body>
</html>
Yes! you can change it on touch/click event by changing source of that java script image.
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.3.min.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 140,
y: stage.getHeight() / 2 - 59,
image: imageObj,
width: 106,
height: 118
});
var filteredYoda = new Kinetic.Image({
x: 320,
y: stage.getHeight() / 2 - 59,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
layer.add(filteredYoda);
// add the layer to the stage
stage.add(layer);
stage.on('click',function(){
imageObj.src = 'http://crushlabs.com/wp-content/uploads/2013/01/jacee-terry-hello-card-business-card-design-back.jpg';
});
// apply grayscale filter to second image
filteredYoda.applyFilter(Kinetic.Filters.Grayscale, null, function() {
layer.draw();
});
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
</script>
var stages = new Array() ;
var limites = new Array() ;
numStage=0;
r = {
'x':65,
'y':120,
'xwidth':335,
'yheight':210
};
limites.push(r);
stages[numStage] = new Kinetic.Stage({
container: 'cmg_canvas_'+numStage,
width: 450,
height: 450
});
//creation image
obj = new Image();
obj.src = 'http://i.imgur.com/zFZgKuS.jpg';
image = new Kinetic.Image({
image: obj,
width: 450,
height: 450
});
// add image to calque
layer = new Kinetic.Layer();
layer.add(image);
stages[numStage].add(layer); //add image to canvas
layer = new Kinetic.Layer();
//set limit x y h l
/*var rect = new Kinetic.Rect({
name: 'limite',
x: limites[numStage].x,
y: limites[numStage].y,
width: limites[numStage].xwidth,
height: limites[numStage].yheight,
stroke: 'black',
strokeWidth: 0.5
});*/
//layer.add(rect);// add to canvas
stages[numStage].add(layer);
$('.cmg_text').live('blur', function(){
idText = 'cmg_line0';
numStage = 0;
drawTextPath(numStage, idText,$(this).val(),50,22,numStage);
//text = getText(this).text;
});
function getSVG(x,y,w,verif) {
halfw = parseFloat((w/2).toFixed(2));
x1 = parseFloat((halfw/2).toFixed(2));
x2 = parseFloat(halfw + x1);
if(parseInt(verif))
{
y1 = parseFloat(y) * 2 +18;
y2 = parseFloat(y) * 2 +18;
}
else
{
y1 = -18;
y2 = -18;
}
str = 'M '+x+','+y+' C '+x1+','+y1+' '+x2+','+y2+' '+w+','+y;
return str;
}
function drawTextPath(numStage, textId,text,valueSlider, newFontSize,numStage){
//'M 0,115 C42,-18 126,-18 165,115';
//'M 0,115 C45,230 180,230 180,115';
var arcOnly = 0;
if(textId == 'cmg_line0')
{
console.log('limites[numStage].yheight/2'+limites[numStage].yheight/2);
console.log('limites[numStage].xwidth'+limites[numStage].xwidth);
svg = getSVG(0,valueSlider,valueSlider*6.3,0);
arcOnly = 0;
}
//alert(svg);
console.log(parseFloat(limites[numStage].y));
console.log(parseFloat(arcOnly));
console.log(parseFloat(limites[numStage].y - arcOnly));
var layer = new Kinetic.Layer({name:'textPathLayer',draggable:true});
var textpath = new Kinetic.TextPath({
name:'TextPath',
id: textId,
//x: 0,
//x: limites[numStage].x + limites[numStage].xwidth/2,
//y: 0,
//y: limites[numStage].y + limites[numStage].yheight/2,
x: limites[numStage].x ,
y: limites[numStage].y + limites[numStage].yheight/2,
fill: '#000',
fontSize: newFontSize,
fontFamily: 'Arial',
text: text,
//offsetX:0,
//offsetY:0,
draggable: true,
dragBoundFunc: function(pos){
p = textParams(this, pos);
return {x: p.newX, y: p.newY};
},
data: svg
});
//
layer.add(textpath);
stages[numStage].add(layer);
//layer.moveToTop();
//layer.draw();
//stages[0].draw();
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/kineticjs/4.6.0/kinetic.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div id="cmg_canvas_0"></div>
<input type='text' class='cmg_text' />
I have to draw a draggable textpath with kineticjs, with text given by an input text, the action is triggered in blur.
I have a stage that contain 3 layers;
Layer for the background, and one layer for the textpath.
My problem that the draggable in the textpath is not working,
i tried to set the text layer in the top, but i didn't get it draggable.
This is my jsfiddle
I have a doubt of inner layer problem.
Thanks in advance.