CreateJS - Collision detection between two createjs.Containers - createjs

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

Related

adobe illustrator script- rectangle resize

יello everybody! I tried to create a script that creats a rectangle of a given size, make a group and a clipping mask and after all that resize it to a diffrent size in mm.
for example I have a graphic with the name "fish400" and I clip it in a rectangle of 400X400 that I create with the script. so far so good. my problem is that I want to resize the clipping with all it's content to 382. when I set the height to be the rec. size-18 it gets the height of 385.1
I'm not a very skilled programmer and the script could be written better but I really don't get my mistake.
here is my code:
var doc = app.activeDocument;
var layers = doc.layers;
var myLayer = layers["Layer 1"]; //this defines the layer that you want to get the selection from
var vals = 0;
var tzim = 0;
var side = 0; //width || height
//mm convertor
function mm(n) {return n * 2.83464566929134;}
doc.selection = null; //ensure there is nothing in the document selected already. this way you only get the selection you want.
var found = false;
for(var a=0 ;a<doc.groupItems.length; a++)
{
if (doc.groupItems[a].name == "fish400") {vals = mm(400); tzim = mm(18); side = 1; found = true;}
}
if (found = true)
{
var rect = doc.pathItems.rectangle(0,0,vals,vals);
app.executeMenuCommand("selectall");
var groupItem = doc.groupItems.add();
var count = selection.length;
for(var i = 0; i < count; i++)
{
var item = selection[selection.length - 1];
item.moveToBeginning(groupItem);
}
groupItem.clipped = true;
item.top = center_point[0] + (item.height/2);
item.left = center_point[1] - (item.width/2);
if (side == 1) {groupItem.height -= tzim;} else if (side == 0) {groupItem.width -= tzim;}
}
If your script works fine for you (it doesn't work for me, though) and all you want is to add resizing for your picture from 400x400 to 382x382 mm you can just to add at the end of your script these lines:
var k = 382/400*100;
groupItem.resize(k,k);
Or:
app.executeMenuCommand("selectall");
var sel = app.selection[0];
var k = 382/400*100;
sel.resize(k,k);

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();

remove ticker for individual object in createjs

I want to remove the listener for individual objects that are animating. I want to remove the ticker for individual objects because they will stop at different times when they reach 200px in y. This code is one frame in Adobe Animate. So this code is not working:
this.stop();
that= this;
var aParticle;
var mySpeed = 12;
var myRotation = 4;
var totalParticles = 5;
var stopParticles = false;
var particleHolder = new createjs.Container();
var count = 0;
var collission_ar = [this.parent.mc_coll0, this.parent.mc_coll1, `this.parent.mc_coll2, this.parent.mc_coll3, this.parent.mc_coll4, this.parent.mc_coll5, this.parent.mc_coll6, this.parent.mc_coll7, this.parent.mc_coll8, this.parent.mc_coll9, this.parent.mc_coll10, this.parent.mc_coll11, this.parent.mc_coll12, this.parent.mc_coll13, this.parent.mc_coll14];`
var totalCollisions = collission_ar.length;
this.addChild(particleHolder);
//stage.update();
var xRange = width;
var yRange = height;
var scaleNum = 1;
//var collisionMethod = ndgmr.checkPixelCollision;
this.scaleX = 1;
this.scaleY = 1;
createParticles()
setTimeout(function(){
removeTimer();
}, 5000)
function createParticles(){
var particle_ar = [];
var randNum = Math.ceil(Math.random() * totalParticles);
aParticle = new lib['MC_leaf'+randNum]();
aParticle.name = 'MC_leaf'+count;
aParticle.x = Math.random() * xRange;
aParticle.y = -Math.random() * 15;
theNum = Math.random() * scaleNum;
aParticle.scaleX = theNum
aParticle.scaleY = theNum
aParticle.alpha = 1;
aParticle.collision = Math.floor(Math.random() * 2);
particleHolder.addChild(aParticle);
aParticle.addEventListener("tick", animateParticle.bind(that));
if(!stopParticles){
timer = setTimeout(function() { createParticles() }, 100);
}
count++;
}
function animateParticle (event){
var part = event.currentTarget;
event.currentTarget.y += mySpeed
event.currentTarget.x += Math.random()/10
event.currentTarget.rotation += myRotation;
if (part.y > 200) {
if(part.name == 'MC_leaf0') console.log('part0 y '+part.y);
part.removeEventListener("tick", animateParticle.bind(that));
}
}
function removeTimer() {
stopParticles = true;
timer = clearInterval();
}
var timer = setTimeout(function() { createParticles() }, 100, that);
So this code is just ignored:
part.removeEventListener("tick", animateParticle.bind(that));
You must pass a reference to the same method in removeEventListener that you used with addEventListener. When you use bind, it generates a wrapper function each time.
// This won't work.
part.removeEventListener("tick", animateParticle.bind(that));
A simple workaround is to store a reference to the bound function, and use that.
aParticle.tickHandler = animateParticle.bind(that);
aParticle.addEventListener("tick", aParticle.tickHandler);
Then use it when removing the listener
part.removeEventListener("tick", part.tickHandler);
There is a better way to handle this though. If you use the utility on() method instead of addEventListener, you can easily remove the method inside the handler.
aParticle.on("tick", animateParticle, that);
// Then when removing:
function animateParticle(event) {
if (conditions) {
event.remove();
}
}
The on() method also has a scope parameter, so you can skip the function binding. It is important to note though that the on() method does its own internal binding, so to remove a listener the usual way, you have to store a reference to it as well.
var listener = target.on("tick", handler, this);
listener.off("tick", listener);
Hope that helps!

Line break in date axis with amcharts

As you can see here http://allopensensors.com/profile/andreas/
the date on x-axis is nonreadable. I'd like to add a line break. How can i solve this?
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.pathToImages = "http://allopensensors.com/amcharts/images/";
chart.dataProvider = chartData;
chart.marginLeft = 10;
chart.categoryField = "year";
chart.dataDateFormat = "YYYY-MM-DD JJ:NN:SS";
// listen for "dataUpdated" event (fired when chart is inited) and call zoomChart method when it happens
chart.addListener("dataUpdated", zoomChart);
// AXES
// category
var categoryAxis = chart.categoryAxis;
// categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
categoryAxis.minPeriod = "200"; // our data is yearly, so we set minPeriod to YYYY
categoryAxis.dashLength = 3;
categoryAxis.minorGridEnabled = true;
categoryAxis.minorGridAlpha = 0.1;
// value
var valueAxis = new AmCharts.ValueAxis();
valueAxis.axisAlpha = 0;
valueAxis.inside = true;
valueAxis.dashLength = 3;
chart.addValueAxis(valueAxis);
// GRAPH
graph = new AmCharts.AmGraph();
graph.type = "smoothedLine"; // this line makes the graph smoothed line.
graph.lineColor = "#d1655d";
graph.negativeLineColor = "#637bb6"; // this line makes the graph to change color when it drops below 0
graph.bullet = "round";
graph.bulletSize = 8;
graph.bulletBorderColor = "#FFFFFF";
graph.bulletBorderAlpha = 1;
graph.bulletBorderThickness = 2;
graph.lineThickness = 2;
graph.valueField = "value";
graph.balloonText = "[[category]]<br><b><span style='font-size:14px;'>[[value]]</span></b>";
chart.addGraph(graph);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chartCursor.cursorAlpha = 0;
chartCursor.cursorPosition = "mouse";
chartCursor.categoryBalloonDateFormat = "JJ:NN:SS";
chart.addChartCursor(chartCursor);
// SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);
chart.creditsPosition = "bottom-right";
// WRITE
chart.write("chartdiv");
});
// this method is called when chart is first inited as we listen for "dataUpdated" event
function zoomChart() {
// different zoom methods can be used - zoomToIndexes, zoomToDates, zoomToCategoryValues
// chart.zoomToDates(new Date(1972, 0), new Date(2200, 0));
chart.zoomToIndexes(chartData.length - 40, chartData.length - 1);
}
To make it readable, you can rotate the labels with custom angle. Try categoryAxis.labelRotation : 45
For Reference: http://www.amcharts.com/demos/column-with-rotated-series/
Hope it helps!

Circular Gauge Gradient - TeeChart - MonoAndroid

I am using TreeChart to make an indicator as shown in the picture. But I have a problem I can not make the three-color gradient to that gauge. This is my code
Steema.TeeChart.TChart tChart = new Steema.TeeChart.TChart(this);
tChart.Panel.Transparent = false;
Steema.TeeChart.Styles.Gauges gauges = new Steema.TeeChart.Styles.Gauges(tChart.Chart);
Steema.TeeChart.Drawing.Gradient g = new Steema.TeeChart.Drawing.Gradient(gauges.Chart);
gauges.bBrush.Gradient.Direction = Steema.TeeChart.Drawing.GradientDirection.DiagonalUp;
gauges.bBrush.Gradient.StartColor = System.Drawing.Color.Red;
gauges.bBrush.Gradient.MiddleColor = System.Drawing.Color.Black;
gauges.bBrush.Gradient.EndColor = System.Drawing.Color.Blue;
gauges.bBrush.Gradient.Visible = true;
gauges.Pen.Color = System.Drawing.Color.FromArgb(5,56,73);
gauges.TotalAngle = 180; // circular arc
gauges.RotationAngle = 180; // arc rotation angle
gauges.HandStyle = Steema.TeeChart.Styles.HandStyle.Triangle; // pointer style
gauges.Center.Style = Steema.TeeChart.Styles.PointerStyles.Circle; // SPHERE center circle style
gauges.Center.HorizSize = 5; // center circle level size
gauges.Center.VertSize = 5; // center circle vertical size
gauges.ShowInLegend = false; // display the legend
gauges.HandDistance = 23; // pointer length
//---------------------------------------------------
gauges.Value = 80;
gauges.Minimum = 0; // minimum;
gauges.Maximum = 100; // maximum value
//----------------------------------------------------
gauges.MinorTickDistance = 0;
gauges.Pen.DashWidth = 23;
gauges.Chart.Axes.Left.AxisPen.Width = 65; // brush width;
gauges.Chart.Axes.Left.AxisPen.Color = System.Drawing.Color.Red;
gauges.Chart.Axes.Left.MinorTickCount = 5; // the scale value scale line number
gauges.Chart.Axes.Left.MinorTicks.Length = 10; // the scale value scale line length of
gauges.Chart.Axes.Left.Ticks.Length = 20; // display the value scale line length of
gauges.Chart.Axes.Left.Increment = 3000; // the scale value of interval size
SetContentView(tChart) ;
I also tried the following lines of code
gauges.CircleGradient.Direction = Steema.TeeChart.Drawing.GradientDirection.DiagonalUp;
gauges.CircleGradient.Visible = true;
gauges.CircleGradient.StartColor = System.Drawing.Color.Green;
gauges.CircleGradient.EndColor = System.Drawing.Color.Red;
gauges.CircleGradient.UseStandardGradient = true;
I hope I help
regards
You should use Steema.TeeChart.Styles.CircularGauge instead of Steema.TeeChart.Styles.Gauges which is a much simpler gauge version. For example, using the code snippet below, you get a similar gauge to the image in your link:
Is this similar to what you are looking for?
tChart1.Header.Visible = false;
Steema.TeeChart.Styles.CircularGauge circularGauge1 = new Steema.TeeChart.Styles.CircularGauge(tChart1.Chart);
circularGauge1.Frame.Visible = false;
circularGauge1.FaceBrush.Visible = false;
circularGauge1.DisplayTotalAngle = 180;
circularGauge1.TotalAngle = 180;
circularGauge1.Value = 200;
circularGauge1.Ticks.Visible = false;
circularGauge1.Minimum = 0;
circularGauge1.Maximum = 1000;
circularGauge1.Axis.AxisPen.Visible = false;
circularGauge1.Axis.Increment = 500;
circularGauge1.RedLine.Visible = false;
circularGauge1.GreenLineStartValue = 0;
circularGauge1.GreenLineEndValue = 1000;
circularGauge1.GreenLine.Gradient.Direction = Steema.TeeChart.Drawing.GradientDirection.LeftRight;
circularGauge1.GreenLine.Gradient.UseMiddle = true;
circularGauge1.GreenLine.Gradient.StartColor = Color.Orange;
circularGauge1.GreenLine.Gradient.MiddleColor = Color.Yellow;
circularGauge1.GreenLine.Gradient.EndColor = Color.Green;
circularGauge1.GreenLine.Pen.Visible = false;