I'm using requirejs to load in Kinetic, and I have a simple script to create a sprite and load it on to the canvas. It loads the sprite in a default idle state that is one frame:
require(['libraries/kinetic'], function(Kinetic){
console.log('Initializing....');
var stage = new Kinetic.Stage({
container : 'canvas',
width : 578,
height : 200
}),
layer = new Kinetic.Layer(),
animations = {
idleRight: [{
x : 343,
y : 2,
width : 26,
height : 58
}]
},
imageObj = new Image();
imageObj.src = '/assets/images/billy.png';
imageObj.onload = function() {
var billy = new Kinetic.Sprite({
x : 25,
y : 25,
image : imageObj,
animation : 'idleRight',
animations : animations,
frameRate : 7
});
// add the shape to the layer
layer.add(billy);
// add the layer to the stage
stage.add(layer);
// start sprite animation
billy.start();
console.log('Done.');
}; // .onload
}); // require
I'm using a shim config for require so that kinetic is loaded properly:
requirejs.config({
baseUrl: '/assets/js',
shim: {
'libraries/kinetic' : {
exports : 'Kinetic'
},
}
});
No matter what I try, I can't get the sprite/image to show up! Any help would be greatly appreciated!
I'm using this image from google as a test sprite:
http://www.nes-snes-sprites.com/ImagesSheet/SuperDoubleDragonSheet2.gif
Ended up using the domeReady requirejs module, and loaded it as per below:
require(['libraries/require/domReady!',
'libraries/kinetic'], function(document, Kinetic){... etc
Related
I'm trying to show an icon on the center of a circle.
Here is my code :
jsFiddle : http://jsfiddle.net/61dkv8tr/2/
(function(){
var base64img = "data:image/gif;base64,R0lGODlhPQBEAPeoAJ[...]==";
var extent = [0, 0, 400, 400];
var sourceV = new ol.source.Vector({ wrapX: false });
var map = new ol.Map({
renderer: 'canvas',
target: 'divMap',
layers: [
new ol.layer.Vector({
source: sourceV
})
],
restrictedExtent: extent,
view: new ol.View({
center: ol.extent.getCenter(extent),
extent: extent, //world limit drag map
resolution : 1
})
});
var radius = 50;
var x = 200;
var y = 200;
var circleGeom = new ol.geom.Circle([x, y], radius);
var feature = new ol.Feature(circleGeom);
feature.setStyle(new ol.style.Style ({
stroke: new ol.style.Stroke({
color: 'black',
width: 1
}),
image: new ol.style.Icon({
src: base64img,
color: '#4271AE',
crossOrigin: 'anonymous',
})
}));
sourceV.addFeature(feature);
})();
The render is just the stroke of the circle. Do I miss something ?
The icon is a small red bus.
PS : I also tried with a relative URL, an absolute URL, a canvas...
Thanks !
OK I found the solution. style.Icon only works if its property 'geometry' is of type geom.Point (or if the feature owns a point as geometry type).
To get around with any type of geometry I use the method getExtent() to calculate the center of the geometry and I create a new one of type Point.
Change the view's opacity with animate({}) method don't change the opacity property of the view.
It's normal?
Related ticket on jira
Test code
var win = Ti.UI.createWindow({
backgroundColor: "white"
});
var view = Ti.UI.createView({
width : 100,height : 100,backgroundColor : "red",opacity : 1.0
});
var label = Ti.UI.createLabel({
width : Ti.UI.FILL,top : 30,color : "red",textAlign : "center",font : {fontSize : 20}
});
var buttons = Ti.UI.iOS.createTabbedBar({
bottom : 30,labels : ["Without animate","With animate"],index : 0,tintColor : "red"
});
var temp = true;
setInterval(function(e){
if(temp){
if(buttons.index == 0)
view.opacity = 0.0;
else
view.animate({ opacity : 0.0 , duration : 0});
}else{
if(buttons.index == 0)
view.opacity = 1.0;
else
view.animate({ opacity : 1.0 , duration : 0});
}
temp = !temp;
label.text = "view opacity: " + view.opacity;
},200);
win.add(label,view,buttons);
win.open();
Everything is working as expected. All you need to know is little bit more info about how animations work in any platform, be it native Android, iOS or Titanium itself.
Doing animations on a View, Button, etc. moves only the rendered pixels on the screen of that element, but their properties' values remains same.
So, if you want, then you can set the View's original left value = 10 and then animate it to 100, and you will find that after completion of this animation - the left is still = 10 (not 100).
Therefore, you need to manually set those properties yourself at the end of the animation by passing a callback in animate() method.
Do remember that any UI element's properties do have their own getter & setter methods which changes the rendering of the element, but vice-versa is not true.
Here's your code (little modified) to play with which will give you what you wanted to see.
var win = Ti.UI.createWindow({
backgroundColor: "white"
});
var view = Ti.UI.createView({
width : 100,height : 100,backgroundColor : "red",opacity : 1.0,
left : 10
});
var label = Ti.UI.createLabel({
width : Ti.UI.FILL,top : 30,color : "red",textAlign : "center",font : {fontSize : 20}
});
var buttons = Ti.UI.iOS.createTabbedBar({
bottom : 30,labels : ["Without animate","With animate"],index : 0,tintColor : "red"
});
var temp = true;
setTimeout(function () {
view.animate({
left : 100,
duration : 1000
}, function () {
view.left = 100; // commenting this line will give you left = 10
label.text = "view left: " + view.left;
});
}, 1000);
win.add(label,view,buttons);
win.open();
I have a problem an hope to find any solution for it.
I am using Kinetic.js to create a HMI solution with special look-and-feel. Therefor I have created a function that creates 3 layers for a stage: a background layer with a grid, a layer with static shapes for the base layout of the HMI-screen and the third layer for all interactive elements (like buttons, valuedisplays and so on...). Now I want to cache the grid and the static layer to improve performance, because this layers will never change until the whole HMI-screen will change...
As a test I started to code the caching for the grid layer using the following code:
// Create a grid layer if showGrid is set to TRUE...
console.log('Start to create background grid if required');
if (this.actualPageConfig.showGrid) {
var grid = new Kinetic.Layer();
for (var x=1; x <= this.cols; x++) {
var eLoc = LCARSElements.posToRealPos(x, 1, this.cols, this.rows);
if (x <= this.actualPageConfig.columns) {
grid.add(new Kinetic.Line({
points: [eLoc.x, eLoc.y, eLoc.x, eLoc.height],
stroke: "red",
strokeWidth: 1,
lineCap: "round",
lineJoin: "round"
}));
}
}
for (var y=1; y <= this.rows; y++) {
var eLoc = LCARSElements.posToRealPos(1, y, this.cols, this.rows);
if (y <= this.actualPageConfig.rows) {
grid.add(new Kinetic.Line({
points: [eLoc.x, eLoc.y, eLoc.width, eLoc.y],
stroke: "red",
strokeWidth: 1,
lineCap: "round",
lineJoin: "round"
}));
}
}
// Add grid layer to stage
//this.stage.add(grid); <-- to be replaced by cache image
// Convert grid into an image and add this to the stage
console.log('convert grid to image to increase performance');
grid.toImage({
width: displayManager.stage.getWidth(),
height: displayManager.stage.getHeight(),
callback: function(img) {
var cacheGrid = new Kinetic.Image({
image: img,
x: 0,
y: 0,
width: displayManager.stage.getWidth(),
height: displayManager.stage.getHeight()
});
console.log('insert grid-image to stage');
displayManager.stage.add(cacheGrid);
console.log('redraw stage...');
displayManager.stage.draw();
}
});
}
My problem is, that's not working. The grid is not visible any more and the console log shows the following error information:
Type error: layer.canvas is undefined
layer.canvas.setSize(this.attrs.width, this.attrs.height); kinetic.js (Zeile 3167)
As I already figured out the error rise when the code "displayManger.stage.add(cacheGrid) will be executed (displayManager is the outside-class where this code snipped reside).
Can anyone see where I made the mistake? When I directly add the layer grid anything works fine...
I have created a jsfiddle to demonstrate the problem: jsfiddle
In fiddle you can run both versions by changing one parameter. Hope this helps....
Thanks for help.
Best regards
Thorsten
Actually, the problem is simpler than you might think - after caching the layer into an image, you're trying to add an image object directly to the stage (you can't do that).
To fix the problem, you need to create a new layer, say cahcedLayer, add the image to cachedLayer, and then add cachedLayer to the stage.
Check out the KineticJS info page to learn more about Node nesting:
https://github.com/ericdrowell/KineticJS/wiki
http://rvillani.com/testes/layer-to-image/
I've made this test and it worked. First, I draw 1000 squares to a layer, add this layer to a hidden stage then make an image from this stage using stage.toDataURL(). When the callback returns, I just create an Image from the data and a Kinetic.Image from the Image. Then I add it to a layer on my main (visible) stage.
Code (be sure to have a div called 'invisible'):
window.onload = function()
{
var stage = new Kinetic.Stage({
width: 520,
height: 480,
container: 'container'
});
var outerStage = new Kinetic.Stage({
width: stage.getWidth(),
height: stage.getHeight(),
container: 'invisible'
});
var layerToCache = new Kinetic.Layer();
var layer = new Kinetic.Layer();
var group = new Kinetic.Group({offset: [stage.getWidth(), stage.getHeight()]});
var anim = new Kinetic.Animation(function(frame){
group.rotate(0.02);
}, layer);
var fills = ['red', 'green', 'blue', 'orange', 'purple', 'cyan',
'black', 'brown', 'forestgreen', 'gray', 'pink'];
for (var i = 0; i < 10000; ++i)
{
(function ()
{
var size = Math.random() * 60 + 20;
var square = new Kinetic.Rect({
width: size,
height: size,
fill: fills[i % fills.length],
x: Math.random() * stage.getWidth() - 20,
y: Math.random() * stage.getHeight() - 20
});
layerToCache.add(square);
})();
}
var squaresImg = new Kinetic.Image();
outerStage.add(layerToCache);
outerStage.toDataURL({
callback: function (dataURL){
outerStage.clear();
var img = new Image();
img.src = dataURL;
img.onload = function () {
squaresImg.setImage(img);
squaresImg.setX(squaresImg.getWidth() >> 1);
squaresImg.setY(squaresImg.getHeight() >> 1);
group.setX(stage.getWidth() >> 1);
group.setY(stage.getHeight() >> 1);
group.add(squaresImg);
layer.add(group);
layer.draw();
anim.start();
}
}
});
var div = document.getElementById('invisible');
div.parentNode.removeChild(div);
stage.add(layer);
}
How would you crop a small portion of a big image (e.g area of an imageview visible in a transparent frame) in appcelerator titanium for both iOS and android? imageAs** functions won't work as they aren't supported below android 3.0 . Here is my code:
var win=Ti.UI.createWindow({backgroundColor: 'white'})
var ImageView = Titanium.UI.createImageView({
width:200, height:200,
});
var cropView = Titanium.UI.createView({
width: 150,
height: 150,
borderColor: 'red',
borderWidth: 1,
zIndex: 1,
});
var button= Ti.UI.createButton({
bottom: 30,
width: 60,
title: 'OK',
zIndex: 1,
})
win.add(cropView)
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success: function(e){
ImageView.image=e.media;
win.add(ImageView)
}, });
button.addEventListener('click',function(e)
{
// crop the visible area
})
I am using iOS 5 and android 2.2. Thanks for your help.
Add ImageView to cropView (rather than to win), position and size imageView so that the portion you want displayed is displayed (using negative values for left and top), and then call cropView.toImage(). You can use the resulting blob in a new image view, save it to a file, email it as an attachment, whatever you want.
Any portion of the image outside of its parents bounds will be cropped, leaving only the portion you specify.
I have done some small changes and now its all functional. Cheers!! :)
var win = Ti.UI.createWindow({
backgroundColor : 'white'
})
var orignal = Titanium.UI.createImageView({
width : Ti.UI.SIZE,
height : Ti.UI.SIZE,
left:5
});
var ImageView = Titanium.UI.createImageView({
width : 200,
height : 200
});
var cropView = Titanium.UI.createView({
top : 10,
width : 150,
height : 150,
borderColor : 'lime',
borderWidth : 1,
zIndex : 1,
left:150
});
var button = Ti.UI.createButton({
bottom : 30,
width : 60,
title : 'CROP',
zIndex : 1,
});
win.add(button);
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success : function(e) {
ImageView.image = e.media;
orignal.image=e.media;
cropView.add(ImageView);
win.add(cropView);
win.add(orignal);
},
});
var CropedImageView = Titanium.UI.createImageView({
top : 200,
width : cropView.width,
height : cropView.height,
left:150
});
button.addEventListener('click', function(e) {
cropView.borderColor='transparent';
CropedImageView.image = cropView.toImage();
win.add(CropedImageView);
});
win.open();
I learnt some of this while my stay at Oodles Technologies.
Here's my contribution :
In this example you will see how to crop image in iOS Titanium.
To crop a image first create scroll view, define its maxZoomScale, minZoomScale.
maxZoomScale:-
Maximum Scaling factor of the scrollable region and its content.
minZoomScale:-
Minimum Scaling factor of the scrollable region and its content
maxZoomSale and minZoomScale we can adjust according to required.
then we have to add image view inside scrollview, then we can zoom in and zoom out image, to crop a image just need to click on crop button.
var window = Ti.UI.createWindow({
backgroundColor : 'white'
});
var scrollView = Ti.UI.createScrollView({
height : 260,
width : Ti.UI.FILL,
maxZoomScale : 4.0,
minZoomScale : 1.0,
zoomScale : 1.0,
});
window.add(scrollView);
var imageView = Ti.UI.createImageView({
height : scrollView.height,
width : scrollView.width,
backgroundColor : "transparent",
anchorPoint : {
x : 0.5,
y : 0.5
},
image : 'Default-568h#2x.png',
});
scrollView.add(imageView);
var button = Ti.UI.createButton({
top : 20,
title : 'Crop Button'
});
window.add(button);
button.addEventListener('click', function(e) {
button.hide();
var cropimage = scrollView.toImage();
var cropImageView = Ti.UI.createImageView({
top : 20,
height : 120,
width : 120,
image : cropimage
});
window.add(cropImageView);
});
window.open();
Here is my
APP.js
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var header = Ti.UI.createView({
height : 20,
width : 303,
top : 0,
backgroundColor : "#abc"
});
win.add(header);
var scroll = Ti.UI.createScrollView({
top : 44,
bottom : 44,
layout : 'vertical'
});
win.add(scroll);
header.addEventListener('click', function(evt) {
fetch_images();
});
win.open();
function fetch_images() {
var xhr = Ti.Network.createHTTPClient({
onload : function() {
myjson = JSON.parse(this.responseText);
for ( i = 0; i < myjson.length; i++) {
Ti.API.debug(i);
var look = new looks(myjson[i])
scroll.add(look);
}
},
onerror : function(e) {
Ti.API.debug("STATUS: " + this.status);
Ti.API.debug("TEXT: " + this.responseText);
Ti.API.debug("ERROR: " + e.error);
if (Titanium.Network.online) {
alert('No reponse from server.');
} else {
alert('Please Check your Internet connectivity.');
}
},
timeout : 5000
});
xhr.open('GET', 'http://xxxxxxx.com/xxxxxxx.json?api_token=xxxxxxxx');
xhr.send();
}
function looks(image_details) {
var look_container = Ti.UI.createView({
height : 325,
width : 303,
top : 10,
layout : 'horizontal',
backgroundColor : "#cac"
});
var look_image = i.UI.createImageView({
width : 303,
top : 0,
left : 0,
right : 0,
image : image_details.image_medium
});
look_container.add(look_image);
return look_container;
}
I am about to pull my hairs from my head.
Working with this for around last 4-5 hours.
Acc. to the code Image should be something like this
But it appears like this.
Any guess whats wrong !! Any help would be grateful ??
As per the code Image should be aligned to top (0px from top). But Image is always down the line in the view and dont stick to the top... ??
-------------------------EDIT---------------------------
I editted my code to check for static JPG images
and its same even for the Images in the resources directory
check this question developer.appcelerator.com/question
code
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
width : '100%',
top : 0,
left : 0,
right : 0,
image : 'hello.jpg'
});
my_container.add(my_image);
win.add(my_container);
my_container.addEventListener('click', function() {
my_image.top = my_image.top - 25;
})
win.addEventListener('click', function() {
my_image.top = my_image.top + 5;
})
win.open();
and image url for the image to be used.
The problem is not the layout properties, it is image scaling! Note first that you are passing a larger image than the view, so Titanium does some scaling under the sheets.
So when you define the width of that ImageView, if the image you pass is bigger than the view, Titanium scales it using its own mechanism, which obviously, is not what you want, since it has been causing you to tear your hair out the past few days. I believe they scale images from the bottom up, causing your weird problem.
To fix this, you need to take control of the image scaling from Titanium, and pass a new, resized image
To do this, we need to get the original height and width of the image, to preserve the aspect ratio, then figure out a new size, resize the image, and pass it to the imageView.
To get the height and width of the image you kind of have to hack around a bit, here is how I did it with SDK 2.1.1.GA:
Get Height and Width of a Blob / Image
// Load the image as a blob to get height information
var imageFile = Ti.Filesystem.getFile('hello.png');
var blobOfImage = imageFile.read();
// Put it in a imageView, since It wont let me get height from a blob for some reason
var imageView1 = Titanium.UI.createImageView({
image: blobOfImage,
width: 'auto',
height: 'auto',
});
// This is the important part, toImage this view and you get the height and width of this image
// For some reason we cant get this from a Blob in SDK 2.1.1.GA
var heightOfImage = imageView1.toImage().height;
var widthOfImage = imageView1.toImage().width;
Now we calculate the aspect ratio for the width (screen size for iPhone of 320).
Aspect Ratio
var aspectRatio = heightOfImage / widthOfImage;
And now we can create the new resized image in the imageview.
New Image!
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
top : 0,
left : 0,
right : 0,
image : blobOfImage.imageAsResized(320, 320*aspectRatio) // Note the resize call to the image blob
});
Here is the final output :
So I guess the lesson is dont trust Titanium to scale your images for you.