how to get fabricJS to work with touch events? - javascript

I have an application developped with phonegap and I am testing the touch support for fabricJS but somehow it doesn't work for me.
I tried creating a custom version here but it doesn't work with it.
I have this jsfiddle where I used another version called fabric_events.js but it doesn't seems to work too. (BTW how do you upload your own version to jsfiddle?)
so I tried the FabricJS touch events demo and it DOES work!!
since the demo worked I tried to download it's own version from http://fabricjs.com/lib/fabric_with_gestures.js but still no luck.
this is my code:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, width=device-width, user-scalable=true" />
<script src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/fabric_with_gestures.js"></script>
<script type="text/javascript" >
$(document).ready
(
function () {
var canvas = new fabric.Canvas('c');
// Do some initializing stuff
fabric.Object.prototype.set({
transparentCorners: false,
cornerColor: 'rgba(102,153,255,0.5)',
cornerSize: 12,
padding: 5
});
alert('fabric.isTouchSupported=' + fabric.isTouchSupported);
var info = document.getElementById('info');
canvas.on({
'touch:gesture': function () {
var text = document.createTextNode(' Gesture ');
info.insertBefore(text, info.firstChild);
},
'touch:drag': function () {
var text = document.createTextNode(' Dragging ');
info.insertBefore(text, info.firstChild);
},
'touch:orientation': function () {
var text = document.createTextNode(' Orientation ');
info.insertBefore(text, info.firstChild);
},
'touch:shake': function () {
var text = document.createTextNode(' Shaking ');
info.insertBefore(text, info.firstChild);
},
'touch:longpress': function () {
var text = document.createTextNode(' Longpress ');
info.insertBefore(text, info.firstChild);
}
});
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function (img) {
img.scale(0.5).set({
left: 150,
top: 150,
angle: -15
});
canvas.add(img);
});
canvas.add(new fabric.Rect({
left: 50,
top: 50,
fill: '#269926',
width: 100,
height: 100,
originX: 'left',
originY: 'top',
hasControls: true,
hasBorders: true,
selectable: true
}));
var obj = new fabric.Rect({
left: 20,
top: 20,
fill: '#555555',
width: 100,
height: 100,
originX: 'left',
originY: 'top',
hasControls: true,
hasBorders: true,
selectable: true
});
canvas.add(obj).renderAll();
canvas.setActiveObject(obj)
//canvas.sendToBack(obj)
}
);
</script>
<title></title>
<style>
canvas {
border: 1px solid #999;
}
</style>
</head>
<body>
<canvas id="c" width="200" height="200" style='z-index:-1'></canvas>
<p id='info' style='background: #eef; width: 583px; padding: 10px; overflow: scroll; height: 80px'></p>
</body>
</html>

Sorry for the late answer. I am working with Fabric.js at the moment and I do not have any problems with gestures. I have tried your code, it is generally working if you care for three things:
1.) Very important: Please remove style='z-index:-1' from the canvas itself. The z-index property specifies the stack order of an element and a negative number will not allow you to interact with the canvas in your example. More information: CSS z-index Property.
2.) Are you sure that you had created a Custom Build with "Interaction" and "Gestures"? "Gestures" is dependent on "Interaction". If you are unsure, create a Custom Build with all modules except "Node" (unless you want to use Node.js later).
3.) Fabric.js and jQuery must be in the subfolder 'js' regarding to your code. But I would think that it was like that already.
Then it should work for you, too.

Related

fabric js fontweight not working

I am using this code to add textbox in canvas using fabric js,
var text = 'Type Text Here';
var textSample = new fabric.Textbox(text, {
left: getCardLeft() + 100,
top: getCardTop() + 10,
width: 200,
height: 20,
fontFamily: 'Helvetica',
fill: getColorPickerForegroundColor(),
fontWeight: '',
fontSize: parseInt('25'),
originX: 'center',
hasRotatingPoint: true,
centerTransform: true,
});
canvas.add(textSample);
Which successfully add textbox into canvas.
Now, if i try to make it bold using this command
canvas.getActiveObject().set("fontWeight", "bold");
canvas.renderAll();
Working, But when try to change it to normal,
canvas.getActiveObject().set("fontWeight", "");
canvas.getActiveObject().set("fontWeight", "100");
canvas.getActiveObject().set("fontWeight", "normal");
canvas.renderAll();
not working.
I don't know where the issue is. Am i doing anything wrong here?.
Its behaving strange
You can see it here.
visit first here
Then visit here
I just take fabric.js from here and replaced with mine, and working all.
The following code works for me. I see two points where I could failed at your side:
canvas.renderAll();
Needed to be rerendered properly. And also:
canvas.setActiveObject(textSample);
was neccessary for me. Because otherwise:
canvas.getActiveObject();
was undefined.
Now a full working code example:
var canvas = new fabric.Canvas('c', { selection: false });
var text = 'Type Text Here';
var textSample = new fabric.Textbox(text, {
left: 300,
top: 50,
width: 200,
height: 20,
fontFamily: 'Helvetica',
fill: "#fac",
fontWeight: '100',
fontSize: parseInt('25'),
originX: 'center',
hasRotatingPoint: true,
centerTransform: true,
});
canvas.add(textSample);
canvas.setActiveObject(textSample);
canvas.getActiveObject().set("fontWeight", "bold");
canvas.renderAll();
canvas.getActiveObject().set("fontWeight", "100");
canvas.renderAll();
Hope that helps.

Raphael-free-transform looses scale value

in the following code re-scaling of the square object goes wrong:
after clicking the button (which apply y-scale factor and make a rectangle out of our square) object displays correct BUT if you touch handles after that the previous scale values erase and square displays again.
I want to be able to make rectangle in a code and re-scale it uniformly using handles afterwards.
How to solve this problem?
<html>
<head>
<title></title>
<script src="scripts/raphael.js"></script>
<script src="scripts/raphael.free_transform.js"></script>
</head>
<body>
<button id="btn" onclick="onClick()">apply scale</button>
<script>
var r = Raphael(100, 0 , 300, 400);
var square = r.rect(100,150, 100, 100).attr({ fill: "#aaa", stroke: "black", opacity: 0.5 });
var ft = r.freeTransform(square, {}, function () {});
ft.setOpts({
attrs: { fill: 'white', stroke: '#000' },
drag: false,
keepRatio: ['axisX', 'axisY'],
size: 5,
scale: ['axisX', 'axisY'],
rotate:false
});
function onClick() {
ft.attrs.scale.y = 2;
ft.apply();
}
</script>
</body>
</html>
jsfiddle is here
When you scale y by 2, it violates keepRatio: ['axisX', 'axisY'] rule. So either you change
`keepRatio: false,`
or you scale by keeping the ratio.
edit:
You can change the aspect ratio by ft.attrs.ratio = 1/2 on button click. see updated js fiddle
To get js.fiddle working i added the line r.setViewBox(0, 0, 300, 400, true);
http://jsfiddle.net/Z2cqT/18/

Kinetic canvas with user text field input

I've pulled out most of my hair trying to find a solution to no avail.
I know this must be easy but being a javascript neophyte I can't seem to wrap my head around it and am hoping someone can help me out!!!
I'm trying to create a simple canvas element that has an image with text (with wrapping) on top of it. The text will come from a text field outside of the canvas (nothing fancy). I've seen where the canvas populates with the text as it is input into the text field which is what I'm looking for (no submit button). Eventually, I will need to add 2 additional text fields with different information, doing the same thing but for right now I'd be happy to get one to work!
The kinetic text tutorial found here (http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-text-tutorial/ - code below) would be perfect if I could only figure out how to get the "complex text" to be pulled from a regular text input field instead of being hard coded!
Any help would be greatly appreciated!
Working code without input text field:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 220
});
var layer = new Kinetic.Layer();
var simpleText = new Kinetic.Text({
x: stage.getWidth() / 2,
y: 15,
text: 'Simple Text',
fontSize: 30,
fontFamily: 'Calibri',
fill: 'green'
});
// to align text in the middle of the screen, we can set the
// shape offset to the center of the text shape after instantiating it
simpleText.setOffset({
x: simpleText.getWidth() / 2
});
// since this text is inside of a defined area, we can center it using
// align: 'center'
var complexText = new Kinetic.Text({
x: 100,
y: 60,
text: 'COMPLEX TEXT\n\nAll the world\'s a stage, and all the men and women merely players. They have their exits and their entrances.',
fontSize: 18,
fontFamily: 'Calibri',
fill: '#555',
width: 380,
padding: 20,
align: 'center'
});
var rect = new Kinetic.Rect({
x: 100,
y: 60,
stroke: '#555',
strokeWidth: 5,
fill: '#ddd',
width: 380,
height: complexText.getHeight(),
shadowColor: 'black',
shadowBlur: 10,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
cornerRadius: 10
});
// add the shapes to the layer
layer.add(simpleText);
layer.add(rect);
layer.add(complexText);
stage.add(layer);
</script>
</body>
</html>
Possible solution: to add one input field, set up event listener which fire on change of its value and then start drawing.
<body>
<div id="container"></div>
<input type="text" id='complexText' size="20"/>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<script defer="defer">
var inputField = document.getElementById('complexText');
inputField.addEventListener('change', function() {
var inputText = this.value;
showText(inputText);
}, false);
function showText(inputText) {
*** here goes all your 'Kinetic' code ***
}
See example at jsBin.

Creating an swf on an swf with jQuery

I have this javascript file which is a modified version of the VideoLightBox script:
jQuery(function(){
var $=jQuery;
var swfID = "video_overlay";
if(!document.getElementById("vcontainer")){
$("body").append($("<div id='voverlay'></div>"));
$("#voverlay").append($("<div id = 'vcontainer'></div>"));
}
$("#videogallery a[rel]").overlay({
api:true,
expose: (0?{
color:'#424542',
loadSpeed:400,
opacity:0
}:null),
effect:"apple",
onClose: function(){
swfobject.removeSWF(swfID);
},
// create video object for overlay
onBeforeLoad: function(){
// check and create overlay contaner
var c = document.getElementById(swfID);
if(!c){
var d = $("<div></div>");
d.attr({id: swfID});
$("#vcontainer").append(d);
};
var wmkText="© 2011 BORKH";
var wmkLink="http://borkh.co.uk";
c = wmkText? $('<div></div>'):0;
if (c) {
c.css({
position:'absolute',
right:'38px',
top:'38px',
padding:'0 0 0 0'
});
$("#vcontainer").append(c);
};
// for IE use iframe
if (c && document.all){
var f = $('<iframe src="javascript:false"></iframe>');
f.css({
position:'absolute',
left:0,
top:0,
width:'100%',
height:'100%',
filter:'alpha(opacity=0)'
});
f.attr({
scrolling:"no",
framespacing:0,
border:0,
frameBorder:"no"
});
c.append(f);
};
var d = c? $(document.createElement("A")):c;
if(d){
d.css({
position:'relative',
display:'block',
'background-color':'',
color:'#626d73',
'font-family': 'RegisterSansBTNDmRegular, Helvetica, Arial',
'font-size':'11px',
'font-weight':'normal',
'font-style':'normal',
'text-decoration': 'none',
padding:'1px 5px',
opacity:.7,
filter:'alpha(opacity=70)',
width:'auto',
height:'auto',
margin:'0 0 0 0',
outline:'none'
});
d.attr({href:wmkLink});
d.html(wmkText);
d.bind('contextmenu', function(eventObject){
return false;
});
c.append(d);
}
// create SWF
var src = this.getTrigger().attr("href");
if (typeof(d)!='number' && (!c || !c.html || !c.html())) return;
if (false){
var this_overlay = this;
// if local
window.videolb_complite_event = function (){ this_overlay.close() };
// if youtoube
window.onYouTubePlayerReady = function (playerId){
var player = $('#'+swfID).get(0);
if (player.addEventListener) player.addEventListener("onStateChange", "videolb_YTStateChange");
else player.attachEvent("onStateChange", "videolb_YTStateChange");
window.videolb_YTStateChange = function(newState){
if (!newState) this_overlay.close()
}
}
}
swfobject.createSWF(
{ data:src, width:"100%", height:"100%", wmode:"opaque" },
{ allowScriptAccess: "always", allowFullScreen: true, FlashVars: (false?"complete_event=videolb_complite_event()&enablejsapi=1":"") },
swfID
);
}
}); });
The script opens a flash swf file in a "popup" lightbox fashion and plays it either from youtube or via a player locally. I was however wondering if it was possible to create a secondary swf to float on top of the player (noting that this of course would have the wmode:"transparent") and hereby create an opening curtain effect revealing the first swf and the player. I've been trying for quite some time now to load the top clip via createSWF and to create an additional div to contain it and float it using absolute position however I can't seem to get it right.. I know that the div float perfectly on top of each other when using:
<head>
<style type="text/css" media="screen">
<!--
#bottom{
position:absolute;
width: 500px;
height: 400px;
}
#top{
position:absolute;
width:500px;
height:400px;
top: 0px;
left: 0px;
}
-->
</style>
</head>
<body>
<div id="bottom">
"MAIN CLIP"
<div id="top">
"CURTAIN EFFECT"
</div>
</div>
However I'm not strong enough in javascripting to transfer it.
Any help, ideas, hints or suggestions are much appreciated!
Thanks
Andreas
I think your idea will work, but could get quite tricky.
What I would recommend instead is creating a "curtain swf" that instead loads something like the Chromeless YouTube player inside of it. This way you can listen for when the video is done loading/buffering and reveal the curtains when that happens.

JQuery resizable problem when dynamically adding elements

ok so i have this script, and what it does is makes an ajax call to a page every time the link is clicked, gets the html element from the ajax puts it into the mainCanvas element, then assign drag and resize features to it.
(example of html recieved from ajax. ###### = the instanceID being passed to it via ajax so the ID is different for each instance)
ajax.php
<div id="Image_######" style=" width:55px; height:55px; position: absolute;">
<img class="Image_######" alt="" title="" src="http://www.imagemagick.org/Usage/thumbnails/hatching_orig.jpg" style="width: 100%; height: 100%;" />
</div>
the problem i am having with this is for some reason only the last element has the abbility to resize, they are all still draggable, but resize is broken for previously added elements as soon as the new element is added.
What i want to do is be able to add multiple elements and resize them all not just the last element added.
i suspect that it may have something to do with how I am appending the response html to the canvas, but I'm not sure. I'm more familiar with standard javascript than i am with the voodoo that is JQuery so any help would be much appreciated.
here is the code below, and here is a link to a running example http://sheac.com/resize-problem/
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.2.0/build/cssreset/reset-min.css">
<link rel="stylesheet" type="text/css" href="media/css/_library/jquery/ui-lightness/jquery-ui-1.8.5.custom.css">
<script type="text/javascript" src="media/js/_library/jquery/jquery-1.4.2.js"></script> <!-- jQuery Base -->
<script type="text/javascript" src="media/js/_library/jquery/jquery-ui-1.8.5.custom.js"></script> <!-- jQuery User-Interface Base -->
<script type="text/javascript" src="media/js/_library/jquery/jquery.ui.resizable.js"></script>
create new instance
<br /><br />
<div id="mainCanvas" style="border: 1px solid #CCC; width: 1000px; height: 500px;"></div>
<script type="text/javascript" language="javascript">
//<![CDATA[
var instanceID = 1000;
var properties = ["draggable", "resizableImage"];
function getInstance(){
var instanceID = getNextInstanceID();
$.get("ajax.php", {instanceID: instanceID},
function(response){
document.getElementById("mainCanvas").innerHTML += response;
runProperties(instanceID);
}
);
}
function getNextInstanceID() {
var iid = instanceID;
instanceID++;
return iid;
}
function runProperties(instanceID) {
if (properties != undefined) {
for (var t in properties) {
assignProperty(properties[t], instanceID);
}
}
}
function assignProperty(property, instanceID) {
switch(property) {
case "draggable":
$("#Image_"+instanceID).addClass(property);
$(function() {
$("." + property).draggable({
grid: [ 16, 16 ],
snap: false,
containment: "#mainCanvas",
scroll: false
});
});
break;
case "resizableImage":
$("#Image_"+instanceID).addClass(property);
$(function() {
$("." + property).resizable({
grid: [ 16, 16 ],
minWidth: 32,
maxWidth: 208,
minHeight: 32,
maxHeight: 208,
aspectRatio: 1/1
});
});
break;
}
}
//]]>
</script>
you make ALL images draggable and resizable in "assignProperty" function.
You just need to do this for new element:
function assignProperty(property, instanceID) {
switch(property) {
case "draggable":
$("#Image_"+instanceID).draggable({
grid: [ 16, 16 ],
snap: false,
containment: "#mainCanvas",
scroll: false
});
break;
case "resizableImage":
$("#Image_"+instanceID).resizable({
grid: [ 16, 16 ],
minWidth: 32,
maxWidth: 208,
minHeight: 32,
maxHeight: 208,
aspectRatio: 1/1
});
break;
}
}

Categories