Titanium appcelerator drag view - titanium

I want to drag a view verticaly inside my app, below is my code.
I have a window with id="win" and a square view (100x100).
var window = $.win;
var lastTouchPosition = 0;
$.demo.addEventListener("touchstart", function(e){
var touchPos = {x:e.x, y:e.y};
lastTouchPosition = $.demo.convertPointToView(touchPos, window);
});
$.demo.addEventListener("touchmove", function(e){
var touchPos = {x:e.x, y:e.y};
var newTouchPosition = $.demo.convertPointToView(touchPos, window);
$.demo.top += Number(newTouchPosition.y) - Number(lastTouchPosition.y);
$.demo.left += Number(newTouchPosition.x) - Number(lastTouchPosition.y);
//lastTouchPosition = newTouchPosition;
});
When i start drag the view i get following WARN : [WARN] : Invalid dimension value (nan) requested. Making the dimension undefined instead.
and my view is not moving.
Could you give me an idea please how i can start drag a view and stop to drag it when i reach a specific vertical position value (eg: the bottom of the viewport)
Thank you for your help.

I would add the touch events to the window/container-view instead like this:
var WIDTH = (OS_ANDROID) ? Ti.Platform.displayCaps.platformWidth / dpi : Ti.Platform.displayCaps.platformWidth;
var HEIGHT = (OS_ANDROID) ? Ti.Platform.displayCaps.platformHeight / dpi : Ti.Platform.displayCaps.platformHeight;
var sx = 0;
var sy = 0;
var cx = 0;
var cy = 0;
var xDistance = 0;
function onTouchStart(e) {
// start movement
sx = e.x;
sy = e.y;
cx = e.x;
cy = e.y;
}
function onTouchMove(e) {
xDistance = cx - sx;
var yDistance = cy - sy;
var rotationStrength = Math.min(xDistance / (WIDTH), 1);
var rotationStrengthY = Math.min(yDistance / (HEIGHT), 1);
var rotationAngel = (2 * Math.PI * rotationStrength / 16);
var scaleStrength = 1 - Math.abs(rotationStrength) / 16;
var scaleStrengthY = 1 - Math.abs(rotationStrengthY) / 16;
var scaleMax = Math.min(scaleStrength, scaleStrengthY);
var scale = Math.max(scaleMax, 0.93);
$.view_card_front.rotation = rotationAngel * 20;
$.view_card_front.translationX = xDistance;
$.view_card_front.setTranslationY(yDistance);
$.view_card_front.scaleX = scale;
$.view_card_front.scaleY = scale;
cx = e.x;
cy = e.y;
}
function onTouchEnd(e) {
// check xDistance
}
$.index.addEventListener("touchmove", onTouchMove);
$.index.addEventListener("touchstart", onTouchStart);
$.index.addEventListener("touchend", onTouchEnd);
in the XML there is a <View id="view_card_front"/> with touchEnabled:false
This will give you a nice smooth movent (and a rotation in this example)

Related

Set map borders to not cross inside the view area

I am trying to translate an old flash animation with animate. On the original flash animation the map image is draggable and zoomable but the map ´s borders always stick to the sides of the stage if you pan it or zoom it all the way.
On my test i grabbed some code that allows panning and zooming but the map crosses the stage boundaries if you pan all the way, in fact you can make the map dissapear of the stage.
I think there should be a way to draw like a secondary outer stage and not let the map image go beyond it.
This is the code I have.
var that = this;
var clickedX;
var clickedY;
var isDragging = false;
var friction = 0.85;
var speedX = 0;
var speedY = 0;
var mapOriginalX = this.map.x;
var mapOriginalY = this.map.y;
var mapNudge = 5;
var minScale = 0.25;
var maxScale = 3;
function onMouseWheel(e)
{
var delta;
if (e == window.event)
delta = -10 / window.event.wheelDeltaY;
else
delta = e.detail / 30;
var zoomFactor = delta;
scaleMap(zoomFactor);
}
function mouseDown(e)
{
clickedX = stage.mouseX;
clickedY = stage.mouseY;
isDragging = true;
console.log(stage.mouseX);
console.log(stage.mouseY);
}
function stageMouseUp(e)
{
isDragging = false;
}
function update(e)
{
if (isDragging)
{
speedX = stage.mouseX - clickedX;
speedY = stage.mouseY - clickedY;
}
speedX *= friction;
speedY *= friction;
// saber el tamaño actual del mapa en este punto.
that.map.x += speedX;
that.map.y += speedY;
console.log(that.map.y);
console.log(that.map.x);
clickedX = stage.mouseX;
clickedY = stage.mouseY;
//
}
function resetMap()
{
that.map.x = mapOriginalX;
that.map.y = mapOriginalY;
that.map.scaleX = that.map.scaleY = 1;
}
function zoomMap(e) //control visual
{
if (e.currentTarget == that.plusButton)
scaleMap(-0.1);
if (e.currentTarget == that.minusButton)
scaleMap(0.1);
}
function moveMap(e) //control visual
{
if (e.currentTarget == that.upButton)
speedY -= mapNudge;
else if (e.currentTarget == that.rightButton)
speedX += mapNudge;
else if (e.currentTarget == that.downButton)
speedY += mapNudge;
else if (e.currentTarget == that.leftButton)
speedX -= mapNudge;
}
function scaleMap(amount)
{
var map = that.map; // we will scale de map so this goes first.
map.scaleX -= amount; // same as map.scaleX = map.scaleX - amount
map.scaleY = map.scaleX;
if (map.scaleX < minScale)
map.scaleX = map.scaleY = minScale;
else if (map.scaleX > maxScale)
map.scaleX = map.scaleY = maxScale;
}
// listeners
this.map.on("mousedown", mouseDown.bind(this));
this.resetButton.on("click", resetMap.bind(this));
this.plusButton.on("click", zoomMap.bind(this));
this.minusButton.on("click", zoomMap.bind(this));
this.upButton.on("click", moveMap.bind(this));
this.rightButton.on("click", moveMap.bind(this));
this.downButton.on("click", moveMap.bind(this));
this.leftButton.on("click", moveMap.bind(this));
stage.on("stagemouseup", stageMouseUp.bind(this));
document.getElementById('canvas').addEventListener('mousewheel', onMouseWheel.bind(this));
document.getElementById('canvas').addEventListener('DOMMouseScroll', onMouseWheel.bind(this));
createjs.Ticker.addEventListener("tick", update.bind(this));
resetMap();
One trick I usually use is to create a "fence" procedure that checks bounds and corrects them. It will take some setup though.
To use this method, first set up these variables based on your own scene. Perhaps this is what you meant by defining a "second stage?"
var stageLeft = 0;
var stageRight = 500;
var stageTop = 0;
var stageBottom = 500;
this.map.setBounds(0,0,1462, 1047); // Set the values to match your map
var mapBounds = this.map.getBounds();
Then, add this procedure, or a variation of it based on how your map coordinates are set.
// procedure to correct the map x/y to fit the stage
function fenceMap() {
var map = that.map;
var ptTopLeft = map.localToGlobal(mapBounds.x,mapBounds.y);
var ptBotRight = map.localToGlobal(mapBounds.width,mapBounds.height);
if ((ptBotRight.x - ptTopLeft.x) > (stageRight-stageLeft)) {
if (ptTopLeft.x > stageLeft) {
map.x -= ptTopLeft.x - stageLeft;
speedX = 0;
} else if (ptBotRight.x < stageRight) {
map.x -= ptBotRight.x - stageRight;
speedX = 0;
}
}
if ((ptBotRight.y - ptTopLeft.y) > (stageBottom-stageTop)) {
if (ptTopLeft.y > stageTop) {
map.y -= ptTopLeft.y - stageTop;
speedY = 0;
} else if (ptBotRight.y < stageBottom) {
map.y -= ptBotRight.y - stageBottom;
speedY = 0;
}
}
}
Then, just add to the end of your update(), zoomMap(), moveMap(), and scaleMap() functions:
fenceMap();

React native : Json.stringify cannot serialize cyclic structure

The issue happened here while using canvas property.
I tried to create roulette in react native using canvas property. I successfully used canvas, except I cannot use ctx.drawImage methods. When I tried to use them I got an error like
JSON.Stringify cannot serialize cyclic structures
Here is a code snipet
componentDidMount(){
wheelCanvas = this.updateCanvas();
}
// This is in error while rendering :
ctx.drawImage(wheelCanvas, wheelCanvas.width / 2, wheelCanvas.height / 2);
updateCanvas() {
var outsideRadius = 120;
var textRadius = 100;
var insideRadius = 30;
var canvas = this.refs.canvasRoulette;
let ctx = canvas.getContext("2d");
canvas.width = canvas.height = outsideRadius * 2 + 6;
var x = outsideRadius + 3;
var y = outsideRadius + 3;
ctx.font = "bold 18px Helvetica, Arial";
for (var i = 0; i < rouletteSize; i++) {
var angle = i * arc;
ctx.fillStyle = colors[i];
ctx.beginPath();
ctx.arc(x, y, outsideRadius, angle, angle + arc, false);
ctx.arc(x, y, insideRadius, angle + arc, angle, true);
ctx.strokeStyle = "#fff";
ctx.lineWidth = 1;
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "#fff";
ctx.translate(
x + Math.cos(angle + arc / 2) * textRadius,
y + Math.sin(angle + arc / 2) * textRadius
);
ctx.rotate(angle + arc / 2 + Math.PI);
var text = numbers[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 5);
ctx.restore();
}
return canvas;
}

Createjs function

I am trying to convert an old simulation from Flash to createjs with animate cc. The only code you have is to rotate a piece but I can not get it to work. This code not work:
function spinit()
{
var ang = myangle * Math.PI / 180;
this.pin1.x = disk1.x + R * Math.cos(ang);
this.pin1.y = disk1.y + R * Math.sin(ang);
this.yoke1.x = pin1.x;
this.disk1.rotate = myangle;
this.myangle = myangle + 1;
if (myangle > 360)
{
myangle = 0;
}
}
var myangle = 0;
var R = 90;
setInterval(spinit, 5);
Chances are good this is a scope issue. Your spinit method is being called anonymously, so it won't have access to any of your frame content referenced with this. You can get around this by scoping your method, and binding your setInterval call.
this.spinit = function() // 1. scope the function
{
var ang = myangle * Math.PI / 180;
this.pin1.x = disk1.x + R * Math.cos(ang);
// etc
setInterval(spinit.bind(this), 5); // 2. bind this so it calls in the right scope.
}
Make sure to call this.spinit().
Hope that helps!

createjs Y position inside of movieclip

I have a graphic in an animation playing within a movieclip
What I want to do is get the x and y position of the graphic inside of that movieclip as it animates.
but I'm finding that the x an y don't update, even though at the moment, I'm checking within the tick function, I'm using globalToLocal
function tickHandler(event) {
//get the x and y of this mc using globalToLocal
console.log(exportRoot.game_anim.meterMC.awd.globalToLocal(exportRoot.game_anim.meterMC.awd.x, exportRoot.game_anim.meterMC.awd.y))
stage.update();
}
exportRoot.gotoAndStop("game")
exportRoot.game_anim.meterMC.arrowYou.addEventListener("mousedown",function (evt) {
var _this = evt.target
var mouseRight = 0;
var mouseLeft = 180;
var offset = {x: _this.x - evt.stageX, y: _this.y - evt.stageY};
evt.addEventListener("mousemove" , function(ev){
// )
var pt = exportRoot.game_anim.meterMC.globalToLocal(stage.mouseX, stage.mouseY)
if ( pt.y > mouseLeft){
percent = 100;
} else if (pt.y < mouseRight){
percent = 0;
} else {
percent = Math.round(((pt.y - mouseRight) / (mouseLeft - mouseRight)*100));
_this.y = pt.y;
}
if ( pt.y > mouseLeft){
}
;
})
});
Try using localToGlobal with a static point in your target clip. For example:
var pt = myMC.subMC.localToGlobal(0,0);
console.log(pt.x, pt.y);

CreateJS - Collision detection between two createjs.Containers

I currently have this working in a desktop browser but not on touch devices because I update the variables I need on mouseover. So to get around this I am trying to check for collision detection between two containers and then update the needed variables. The items should snap to the placeholder positions when a collision between the two is detected. The catch is that items and placeholders are placed dynamically any item must be able to snap to any placeholder.
var placeholders,items,selectedItem,collision,startX, startY, snapX, snapY, xpos, ypos;
var stage = new createjs.Stage("canvas");
createjs.Touch.enable(stage);
createjs.Ticker.addEventListener("tick", tick);
function init(){
xpos = 0;
ypos = 120;
container = new createjs.Container();
stage.addChild(container);
placeholders = new createjs.Container();
placeholders.name = "placeholders"
stage.addChild(placeholders);
items = new createjs.Container();
stage.addChild(items);
for(i=0;i<2;i++){
placeholder = new CustomContainer(i, "#ff0000", 100,100);
placeholder.setBounds(0,0,100,100);
placeholder.cursor = "pointer";
placeholder.x = xpos;
placeholder.name = "placeholder"+i
container.addChild(placeholder)
xpos+= (placeholder.getBounds().width + 10);
}
xpos = 0;
for(j=0;j<2;j++){
item = new CustomContainer(j, "#0000ff", 100,100);
item.active = false;
item.setBounds(0,0,100,100);
item.name = "item"+j;
item.x = xpos;
item.y = ypos;
item.startX = xpos;
item.startY = ypos;
container.addChild(item)
item.addEventListener("mousedown", selectItem);
xpos+= (item.getBounds().width + 10);
}
stage.addChild(placeholders,items);
}
function selectItem(evt) {
selectedItem = evt.target.parent;
selectedItem.mouseEnabled = false;
evt.addEventListener("mousemove", function(ev) {
moveItem(ev);
})
evt.addEventListener("mouseup", function(ev) {
selectedItem.mouseEnabled = true;
if(collision){
//New position based on the hitTest
//selectedItem.x = ;
//selectedItem.y = ;
}else{
selectedItem.x = selectedItem.startX;
selectedItem.y = selectedItem.startY;
}
})
}
function moveItem(evt){
pt = placeholders.globalToLocal(stage.mouseX, stage.mouseY);
obj = evt.target.parent;
obj.x = pt.x - 50;
obj.y = pt.y - 50;
//selectedItem collision with placeholder
collision = obj.hitTest(pt.x,pt.y)
}
function tick(evt) {
stage.update();
}
$(document).ready(init());
I am just not getting the hitTest right. You can see the working code below.
http://jsfiddle.net/non_tech_guy/2d68W/4/
The hittest will test pixel-perfect hit. I believe you're looking for a collision test.
Try this: https://github.com/olsn/Collision-Detection-for-EaselJS