i wish to scale a text layer by button click.
var messageLayer = new Kinetic.Layer();
function writeMessage(message, xx, yy) {
var context = messageLayer.getContext();
context.font = '12pt Calibri';
context.fillStyle = 'white';
wrapText(context, message, xx, yy, seat_size, seat_size);
}
stage.add(messageLayer);
writeMessage(text, xx, yy);
document.getElementById('zoomInBtn').onclick = function zoomInStage(){
stage.setScale(2);
stage.draw();
}
I'm not sure why but this seems not working..
Thanks for helping.
Hi thanks for pointing out my mistake.
but after i add the y value and this is still not working ....
below are my code:
enter <!DOCTYPE HTML>
<html>
<body>
<div id="container"></div>
<button id="scaleme" style="margin-left:10px;">Scale</button>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.0-beta2.js"></script>
<script>
function writeMessage(messageLayer, message) {
var context = messageLayer.getContext();
messageLayer.clear();
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var messageLayer = new Kinetic.Layer();
stage.add(messageLayer);
writeMessage(messageLayer, 'text text text');
document.getElementById('scaleme').onclick = function scale(){
messageLayer.setScale(2,2);
}
</script>
</body>
</html>
please helppp....thanks!
From the API docs:
this is the format:
setScale(x, y)
So you are missing the y parameter it seems.
If you do
stage.setScale(2,2);
then the whole stage will be scaled, but if you want just the text layer to be scaled:
messageLayer.setScale(2,2);
lastly, if you want to be fancy, you can do a transition to zoom to the text:
messageLayer.on('click', function(){
messageLayer.transitionTo({
scale: {
x: 2,
y: 2
},
duration: 1,
easing: 'elastic-ease-out' // this one is not really necessary, just for show
});
});
EDIT:
Since you are using canvas primitives, do this: http://jsfiddle.net/mmqXK/
var context = messageLayer.getContext();
context.scale(1, 0.5);
messageLayer.draw();
writeMessage(messageLayer, 'text text text');
Related
I am trying to display and refresh periodically some server data using dgrid and derivative of Request dstore. The data are paginated and needs to be updated periodically. As a first naive approach I tried to call Dgrid.refresh() with setInterval. However, that results in complete rebuilding of grid rows which visually creates flickering effect. Using Trackable to the store does not help. Can anyone advise me how to refresh rows in the dgrid which would only update changed rows?
Here is my code reproducing the issue:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DGrid flickering on slow updates</title>
<style>
#import "./dojo-release-1.11.1/dojo/resources/dojo.css";
#import "./dojo-release-1.11.1/dijit/themes/claro/claro.css";
#import "./META-INF/resources/webjars/dgrid/1.0.0/css/dgrid.css";
#import "./META-INF/resources/webjars/dgrid/1.0.0/css/skins/claro.css";
html, body {
padding: 10px;
width: 100%;
height: 100%;
}
</style>
<script>
var dojoConfig = {
async:true,
baseUrl: "./",
packages:[
{ name:"dojo", location:"dojo-release-1.11.1/dojo" },
{ name:"dijit", location:"dojo-release-1.11.1/dijit" },
{ name:"dgrid", location:"META-INF/resources/webjars/dgrid/1.0.0" },
{ name:"dstore", location:"META-INF/resources/webjars/dstore/1.1.1" }
]
};
</script>
<script src="dojo-release-1.11.1/dojo/dojo.js"></script>
<script>
require(["dojo/parser",
"dojo/dom",
"dojo/_base/declare",
"dstore/Store",
"dstore/Trackable",
"dstore/Cache",
"dstore/Memory",
"dstore/QueryResults",
"dojo/Deferred",
"dgrid/Grid",
"dgrid/Keyboard",
"dgrid/Selection",
"dgrid/extensions/Pagination",
"dojo/domReady!"],
function(parser, dom, declare, Store, Trackable, Cache, Memory, QueryResults, Deferred, Grid, Keyboard, Selection, Pagination)
{
parser.parse();
console.log("Parsed");
var makeSlowRequest =
function(kwArgs)
{
var responseDeferred = new Deferred();
var responsePromise = responseDeferred.promise;
// resolve promise in 2 seconds to simulate slow network connection
setTimeout(function ()
{
console.log("Generating response");
var data = {items: [], total: 100};
kwArgs = kwArgs || {start:0, end:100};
for(var i = kwArgs.start; i < kwArgs.end; i++)
{
data.items.push({id: "id-" + i,
name: "test-" + i,
value: Math.floor((Math.random() * 10) + kwArgs.start)
});
}
responseDeferred.resolve(data);
}, 2000);
return new QueryResults(responsePromise.then(function (data) { return data.items; }),
{ totalLength: responsePromise.then(function (data) { return data.total;}) });
};
var SlowStore = declare("SlowStore",
[Store, Trackable],
{ fetch: function (kwArgs) { return makeSlowRequest(kwArgs); },
fetchRange: function (kwArgs) { return makeSlowRequest(kwArgs); }
});
var store = new SlowStore();
var TestGrid = declare([Grid, Keyboard, Selection, Pagination]);
var grid = new TestGrid({
collection: store,
columns: {name: "Name", value: "Value"},
rowsPerPage: 10,
selectionMode: 'single',
cellNavigation: false,
className: 'dgrid-autoheight',
pageSizeOptions: [10, 20],
adjustLastColumn: true
}, dom.byId("grid"));
grid.startup();
// update grid every 5 seconds
var timer = setInterval(function(){console.log("Refreshing grid"); grid.refresh();}, 5000);
});
</script>
</head>
<body class="claro">
<div id="grid"></div>
</body>
</html>
I am guessing that instead of calling refresh I need get the request range from the dgrid (possibly using aspect on gotoPage) and call store.fetchRange(), iterate over the results, compare each item with previous results and invoke store.update or store.add or store.delete. I suppose that would give me what I want but before taking this approach I wondering if there is an easier way to refresh dgrid with updated data. Using Cache store does not work as it expects to fetch all the data from the server:
var store = Cache.create(new SlowStore(), {
cachingStore: new (Memory.createSubclass(Trackable))()
});
How to print SVG elements that are built by jsPlumb.
Known that getting all SVG Elements drawen by jsPlumb is retrieved by this code :
var uiJsPlumbConnectors=jsPlumb.getAllConnections().map(function(conn){return conn.canvas;})
All connectors are SVG elements :
Using html2canvas to print all connectors (SVG), it does not work :
html2canvas(uiJsPlumbConnectors).then(function(c){
window.open(c.toDataURL('image/png'))
});
An image has been generated , however, it is an emply image .
FIDDLE
It seems that html2canvas does not support yet multi-elements drawing ?
Last time I checked html2canvas was not able to convert SVGs, you will need another script to handle that.
The steps:
transfer html elements to canvas
transfer svg elements to canvas
export canvas
I used https://code.google.com/p/canvg/ to export to the same canvas after using html2canvas. Hope that helps you.
I just implemented this
<%--stuff for printing--%>
<script type="text/javascript" src="../../../../Scripts/Print/html2canvas.js"></script>
<script src="<%=AdminPath%>Scripts/canvg/rgbcolor.js" type="text/javascript"></script>
<script src="<%=AdminPath%>Scripts/canvg/StackBlur.js" type="text/javascript"></script>
<script src="<%=AdminPath%>Scripts/canvg/canvg.js" type="text/javascript"></script>
jsplumb div
<div class="demo statemachine-demo" id="statemachine-demo" style="margin: 0px;">
</div>
hidden div for printing
<div id="canvasDiv" style='visibility:hidden;' >
</div>
function renderImage()
{
var statemachinediv = document.getElementById('statemachine-demo');
html2canvas([statemachinediv], {
onrendered: function (canvas) {
document.getElementById('canvasDiv').appendChild(canvas);
var svgList = $(statemachinediv).find( "svg" );
svgList.each(function(index, value) {
try
{
var svgExample = this;
var serializer = new XMLSerializer();
var svgMarkup = serializer.serializeToString(svgExample);
if(svgMarkup.indexOf("_jsPlumb_connector") > -1)
{
var leftIndex = svgMarkup.indexOf("left: ");
var endOfLeft = svgMarkup.indexOf("px", leftIndex);
var leftPosition = svgMarkup.substring(leftIndex+6, endOfLeft );
var left = parseInt(leftPosition);
var topIndex = svgMarkup.indexOf("top: ");
var endOfTop = svgMarkup.indexOf("px", topIndex);
var topPosition = svgMarkup.substring(topIndex+5, endOfTop );
var top = parseInt(topPosition);
svgMarkup = svgMarkup.replace('xmlns="http://www.w3.org/2000/svg"','');
var connectorCanvas = document.createElement('canvas');
canvg(connectorCanvas, svgMarkup); //add connector to canvas
var context = canvas.getContext('2d');
context.drawImage(connectorCanvas, left, top);
}
}
catch(err)
{
showBalloon('error in print');
}
});
var stateMachineName = $("#stateMachineDropDown option:selected").text();
var data = canvas.toDataURL('image/png');
var mywindow = window.open('', 'my div', 'height=400,width=600');
mywindow.document.write('<html><head><title>' + stateMachineName + '</title>');
mywindow.document.write('</head><body ><table><tr><td>');
mywindow.document.write('</td></tr></table><img src="' + data + '" />');
mywindow.document.write('</body></html>');
mywindow.print();
}
});
return false;
}
Its a old question, but, this helped me. Mode details.
$clone.find('.jtk-connector').each(function () {
// for every SVG element created by JsPlumb for connections...
var left = parseInt(this.style.left, 10) + 'px';
var top = parseInt(this.style.top, 10) + 'px';
this.removeAttribute('style');
this.removeAttribute('position');
this.setAttribute('width', parseInt(this.getAttribute('width'), 10) + 'px');
this.setAttribute('height', parseInt(this.getAttribute('height'), 10) + 'px');
this.setAttribute('preserveAspectRatio', 'xMidYMid meet');
this.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
// this.children[0] is the path for connection line
// this.children[1] is the path for connection arrow shape
this.children[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
this.children[1].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
this.setAttribute('viewbox', '0 0 ' + parseInt(this.getAttribute('width'), 10) + ' ' + parseInt(this.getAttribute('height'), 10));
this.children[0].setAttribute('stroke-width', '2px');
this.children[0].setAttribute('stroke', '#c9c9c9');
this.children[1].setAttribute('fill', '#c9c9c9');
this.children[1].setAttribute('stroke', '#c9c9c9');
$clone.find(this).wrap('<span style="position: absolute; left: ' + left + '; top: ' + top + ';"></span>');
});
This is my code:
var Editor = {
layer: new Kinetic.Layer(),
map: null,
init: function () {
var stage = new Kinetic.Stage({
container: 'board',
width: 800,
height: 800
})
this.map = new Kinetic.Shape({
sceneFunc: function(context) {
context.beginPath();
context.moveTo(0, 0);
context.lineTo(mapWidth, 0);
context.lineTo(mapWidth, mapHeight);
context.lineTo(0, mapHeight);
context.closePath();
context.fillStrokeShape(this);
},
x: 0,
y: 0,
fill: 'green',
draggable: true
})
this.layer.add(this.map)
stage.add(this.layer)
}
}
I want to change the colors of the pixels in the rectangle. Colors of pixels will be generated by the "diamond-square" algorithm. Is it possible to change the colors of individual pixels? If so, how can I do this?
[ Changed answer ]
Use an offscreen html canvas to overlay the pixels in your "diamond-square" algorithm.
Demo: http://jsfiddle.net/m1erickson/6mDSm/
<!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:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var mapWidth=50;
var mapHeight=75;
// use an offscreen canvas as a pixel-map overlaying the green map
var pixelCanvas=document.createElement("canvas");
var ctx=pixelCanvas.getContext("2d");
pixelCanvas.width=mapWidth;
pixelCanvas.height=mapHeight;
pixelCanvas.pixels=[]
pixelCanvas.setPixel=function(x,y,color){
ctx.fillStyle=color;
ctx.fillRect(x,y,1,1);
};
// create a group
// that holds the green map background and pixel-map overlay
var mapGroup=new Kinetic.Group({
x:30,
y:30,
width:mapWidth,
height:mapHeight,
draggable:true
});
layer.add(mapGroup);
// the green background
var map=new Kinetic.Rect({
x:0,
y:0,
width:mapWidth,
height:mapHeight,
fill:"green"
});
mapGroup.add(map);
// an image overlay that
// gets "live-updates" from an offscreen canvas
var pixels=new Kinetic.Image({
x:0,
y:0,
image:pixelCanvas
});
mapGroup.add(pixels);
layer.draw();
// testing
var y=15;
$("#add").click(function(){
for(var i=0;i<5;i++){
pixelCanvas.setPixel(15,y,"red");
pixelCanvas.setPixel(25,y,"gold");
pixelCanvas.setPixel(35,y++,"blue");
}
pixels.draw();
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="add">Add test Pixels</button>
<div id="container"></div>
</body>
</html>
Note: my previous answer using Kinetic.Shape was leaving an undesirable "ghost"
I had loaded image in canvas using fabric.Image.fromURL and working fine with default image width and height.
Now I want to minimize width and height of an image.
How to do this?
Thanks in advance.
Hope this will help
var src; //Image source here
fabric.Image.fromURL(src, function(oImg) {
oImg.scaleToWidth(50);
oImg.scaleToHeight(50);
});
We can use scalex / scaley to set height / width as below.
fabric.util.loadImage(imgsrc, function (img) {
var legimg = new fabric.Image(img, {
left: 30,
top: marker.top,
scaleX: 20 / img.width,
scaleY: 20 / img.height
});
canvas.add(legimg);
canvas.renderAll();
});
Thanks
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 0, top: 0, angle: 00,width:100, height:100}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({format: 'png', quality: 0.8});
});
};
reader.readAsDataURL(file);
});
canvas{
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file"><br />
<canvas id="canvas" width="450" height="450"></canvas>
We can set width and height.
Check this JSfiddle: https://jsfiddle.net/varunPes/8gt6d7op/5/
This working code I have tested:
fabric.Image.fromURL(el.src, function(image) {
image.set({
left: left,
top: top,
angle: 0,
padding: 10,
cornersize: 10,
hasRotatingPoint:true
});
image.scaleToHeight(100);
image.scaleToWidth(200);
canvas.add(image);
});
Work with the image scale properties and not the image size. This worked for me. When I had set the image width and height, and not the scale, when I applied a filter it reset back to original width and height because the scale was 1.0. Hope this helps.
Well I am not sure how are you trying to do it but you could while
adding the image use canvas object in the editor and pass it the Image
in a function called centerObject. Here is the code that worked for
me.
My ReactJS code centers a shirt image in the canvas as given below
const { editor, onReady } = useFabricJSEditor()
const add_image = () => {
fabric.Image.fromURL('assets/custom/shirt_green.png',(oImg) => {
oImg.scaleToHeight(240)
oImg.scaleToWidth(240)
editor.canvas.add(oImg)
editor.canvas.centerObject(oImg)
})
}
Over to the frontend UI we render using
<div>
<FabricJSCanvas className={styles.canvas} onReady={onReady} />
</div>
Is it possible using the spotify apps API to create one of these widgets filled with my data of choice?
Yes, by using import/scripts/pager. Here's an example, extracted and simplified from the "What's New" app. Your pager.js:
"use strict";
sp = getSpotifyApi(1);
var p = sp.require('sp://import/scripts/pager');
var dom = sp.require('sp://import/scripts/dom');
exports.init = init;
function init() {
var pagerSection = dom.queryOne('#pager');
var datasource = new DataSource([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
var options = {
perPage: 5,
hidePartials: true,
orientation: 'vertical', // 'vertical', 'horizontal'
pagingLocation: 'top', // 'top', 'bottom'
bullets: false,
listType: 'list', // 'table', 'list'
context: 'aToplist' // some string unique for each pager
};
var pager = new p.Pager(datasource, options);
pager.h2.innerHTML = "Example Pager";
dom.adopt(pagerSection, pager.node);
}
function DataSource(data) {
var data = data;
this.count = function() {
return data.length;
};
this.makeNode = function(index) {
var dataItem = data[index];
var li = new dom.Element('li');
var nameColumn = new dom.Element('div', {
className: 'nameColumn',
html: '<div class="nameColumn">'+
'Name' + dataItem + ''+
'Creator' + dataItem +''+
'</div>'
});
dom.adopt(li, nameColumn);
return li;
};
}
Your index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="pager.css">
</head>
<body onload="sp = getSpotifyApi(1); sp.require('pager').init();">
<div id="wrapper">
<section class="toplists" id="bottomToplists">
<section id="pager" class="playlists playlistsTable toplist"></section>
</section>
</div>
</body>
</html>
And lastly, copy the whatsnew.css into your project and rename it to pager.css. You will of course need to clean up the css and modify the elements in your index.html to fit with your app but this is a good starting point.
The "What's New" app also has an example of a horizontal pager with album artwork. Take a look at this question and answer to figure out how to extract the source of the app.
Also note that I am not sure whether the pager.js will be part of the public API. If not then you can of course extract it into your own pager widget and use it anyway.