Add a group to a follower - Phaser 3 - html

I'm noob at Phaser 3 and trying to add a group (2 sprites) in a follower. The code works when I use a sprite at 'add.follower'.
function create () {
var bola = this.add.group();
bola.create(0, 0, 'bola15');
bola.create(0, 0, 'bolasombra');
var line1 = new Phaser.Curves.Line([ 100, 100, 500, 100 ]);
var line2 = new Phaser.Curves.Line([ 500, 100, 500, 500 ]);
path1 = this.add.path();
path1.add(line1);
path1.add(line2);
var mover = this.add.follower(path1, 0, 0, bola);
mover.startFollow({
positionOnPath: true,
duration: 3000,
yoyo: false,
repeat: 0,
rotateToPath: false,
verticalAdjust: true
});
}
That's what I got:
Any solution for that, or other way to make something like that?
Edit:
Have tried with 'container' and got the same result:
bola = this.add.container(0,0);
bola1 = this.add.sprite(0,0,'bola15');
bola2 = this.add.sprite(0,0,'bolasombra');
bola.add(bola1);
bola.add(bola2);

At current state, PathFollower is set up to take in only a single GameObject. Unfortunately, this means you'll have to add your group items to a follower one by one. You can set up a loop to run through your group items and create the path followers like this:
for (var i = 0; i < bola.children.entries.length; i++) {
var mover = this.add.follower(path1, 0, 0, bola.children.entries[i].texture.key);
mover.startFollow({
positionOnPath: true,
duration: 3000,
yoyo: false,
repeat: 0,
rotateToPath: false,
verticalAdjust: true
});
}
Check this example from the Phaser 3 labs to see another example of how you can use multiple items with the same path if the group structure isn't important to your game.

Related

Google Charts column chart how to change vertical axis scale?

I have a column chart which I am trying to set the vertical axis scale to whole numbers i.e. 0, 1, 2... instead of 0, 0.5, 1...
Using vAxis : {format : '#'} merely rounds up the decimals, leaving duplicates i.e. 0, 1, 1, 2, 2...
Using vAxis : { gridlines : { count : 5 // for example } } does not seem to have an effect.
Ticks look like a solution but my question is what if my chart is to be dynamic? If I don't know what the max number of jobs would be, so as to set the ticks?
The last resort seems to be putting a height constraint on the chart, forcing the v-axis unit to be larger.
Thank you in advance!
to use ticks and still be dynamic,
you can use data table method getComumnRange(columnIndex)
to determine the min and max values of the y-axis values
then use those values to build the ticks array,
see following working snippet...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['category', 'value'],
['a', 1],
['b', 10],
['c', 4],
['d', 3],
['e', 7]
]);
var yAxisRange = data.getColumnRange(1);
var ticks = [];
for (var i = 0; i <= yAxisRange.max; i++) {
ticks.push(i);
}
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, {
vAxis: {
format: '0',
ticks: ticks
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Restore sectionBox in forge viewer

How to get bounding box info of intersection box in forge viewer?
i want to restore section extension box bounding value to be restored.for that for below method i get box value.
getSelectionbox
now i want to restore that to viewer/set that saved value to viewer for that is there any method is available?
i used setSectionBox(box) but it isn't worked for me.
Thank you
Here is code sample:
viewer.restoreState(currentState, null, false);
viewer.hide(Object.values(val.hiddenNodes));
if(Object.values(val.isolateNodes).length > 0){
viewer.isolate(Object.values(val.isolateNodes));
}
if(val.cutPlanes.length !== 0){
viewer.loadExtension("Autodesk.Section").then(function(sectionTool){
sectionTool.activate(val.sectionStyle);
var sectionTool = markupsExt.tool.getSectionBoxValues();
const sectionbboxmin = new THREE.Vector3(val.sectionBox[0], val.sectionBox[1], val.sectionBox[2]);
const sectionbboxmax = new THREE.Vector3(val.sectionBox[3], val.sectionBox[4], val.sectionBox[5]);
const box = new THREE.Box3(sectionbboxmin,sectionbboxmax);
box.transform = val.sectionBoxTransform;
sectionTool.setSectionBox(box);
});
}
I just tried applying a custom section box to a model in Forge Viewer using this code snippet:
let box = new THREE.Box3(new THREE.Vector3(-100,-100,-100), new THREE.Vector3(100,100,100));
let sectionExt = viewer.getExtension('Autodesk.Section');
sectionExt.setSectionBox(box);
And the result is this:
So this seems to be working ok. Could you provide more details about how you tried to set the section box?
EDIT:
Here's how you can restore the section box from a list of cutplanes (like the one you can obtain from viewer.getState()):
function restoreSectionBox(viewer, cutplanes) {
let box = new THREE.Box3();
for (const cutplane of cutplanes) {
const normal = new THREE.Vector3(cutplane[0], cutplane[1], cutplane[2]);
const offset = cutplane[3];
const pointOnPlane = normal.negate().multiplyScalar(offset);
box.expandByPoint(pointOnPlane);
}
const sectionExt = viewer.getExtension('Autodesk.Section');
sectionExt.setSectionBox(box);
}
// ...
let cutplanes = [
[1, 0, 0, 40],
[0, 1, 0, 50],
[0, 0, 1, 30],
[-1, 0, 0, 60],
[0, -1, 0, 20],
[0, 0, -1, 70]
];
restoreSectionBox(viewer, cutplanes);

Chart.js dynamic bar width

I have a requirement to render a set of time series data of contiguous blocks.
I need to describe a series of bars which could span many hours, or just minutes, with their own Y value.
I'm not sure if ChartJS is what I should be using for this, but I have looked at extending the Bar type, but it seems very hard coded for each bar to be the same width. The Scale Class internally is used for labels, chart width etc, not just the bars themselves.
I am trying to achieve something like this that works in Excel: http://peltiertech.com/variable-width-column-charts/
Has anyone else had to come up with something similar?
I found I needed to do this and the answer by #potatopeelings was great, but out of date for version 2 of Chartjs. I did something similar by creating my own controller/chart type via extending bar:
//controller.barw.js
module.exports = function(Chart) {
var helpers = Chart.helpers;
Chart.defaults.barw = {
hover: {
mode: 'label'
},
scales: {
xAxes: [{
type: 'category',
// Specific to Bar Controller
categoryPercentage: 0.8,
barPercentage: 0.9,
// grid line settings
gridLines: {
offsetGridLines: true
}
}],
yAxes: [{
type: 'linear'
}]
}
};
Chart.controllers.barw = Chart.controllers.bar.extend({
/**
* #private
*/
getRuler: function() {
var me = this;
var scale = me.getIndexScale();
var options = scale.options;
var stackCount = me.getStackCount();
var fullSize = scale.isHorizontal()? scale.width : scale.height;
var tickSize = fullSize / scale.ticks.length;
var categorySize = tickSize * options.categoryPercentage;
var fullBarSize = categorySize / stackCount;
var barSize = fullBarSize * options.barPercentage;
barSize = Math.min(
helpers.getValueOrDefault(options.barThickness, barSize),
helpers.getValueOrDefault(options.maxBarThickness, Infinity));
return {
fullSize: fullSize,
stackCount: stackCount,
tickSize: tickSize,
categorySize: categorySize,
categorySpacing: tickSize - categorySize,
fullBarSize: fullBarSize,
barSize: barSize,
barSpacing: fullBarSize - barSize,
scale: scale
};
},
/**
* #private
*/
calculateBarIndexPixels: function(datasetIndex, index, ruler) {
var me = this;
var scale = ruler.scale;
var options = scale.options;
var isCombo = me.chart.isCombo;
var stackIndex = me.getStackIndex(datasetIndex);
var base = scale.getPixelForValue(null, index, datasetIndex, isCombo);
var size = ruler.barSize;
var dataset = me.chart.data.datasets[datasetIndex];
if(dataset.weights) {
var total = dataset.weights.reduce((m, x) => m + x, 0);
var perc = dataset.weights[index] / total;
var offset = 0;
for(var i = 0; i < index; i++) {
offset += dataset.weights[i] / total;
}
var pixelOffset = Math.round(ruler.fullSize * offset);
var base = scale.isHorizontal() ? scale.left : scale.top;
base += pixelOffset;
size = Math.round(ruler.fullSize * perc);
size -= ruler.categorySpacing;
size -= ruler.barSpacing;
}
base -= isCombo? ruler.tickSize / 2 : 0;
base += ruler.fullBarSize * stackIndex;
base += ruler.categorySpacing / 2;
base += ruler.barSpacing / 2;
return {
size: size,
base: base,
head: base + size,
center: base + size / 2
};
},
});
};
Then you need to add it to your chartjs instance like this:
import Chart from 'chart.js'
import barw from 'controller.barw'
barw(Chart); //add plugin to chartjs
and finally, similar to the other answer, the weights of the bar widths need to be added to the data set:
var data = {
labels: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.7)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 30, 56, 65, 40],
weights: [1, 0.9, 1, 2, 1, 4, 0.3]
},
]
};
This will hopefully get someone onto the right track. What I have certainly isn't perfect, but if you make sure you have the right number of weight to data points, you should be right.
Best of luck.
This is based on the #Shane's code, I just posted to help, since is a common question.
calculateBarIndexPixels: function (datasetIndex, index, ruler) {
const options = ruler.scale.options;
const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options) : computeFitCategoryTraits(index, ruler, options);
const barSize = range.chunk;
const stackIndex = this.getStackIndex(datasetIndex, this.getMeta().stack);
let center = range.start + range.chunk * stackIndex + range.chunk / 2;
let size = range.chunk * range.ratio;
let start = range.start;
const dataset = this.chart.data.datasets[datasetIndex];
if (dataset.weights) {
//the max weight should be one
size = barSize * dataset.weights[index];
const meta = this.chart.controller.getDatasetMeta(0);
const lastModel = index > 0 ? meta.data[index - 1]._model : null;
//last column takes the full bar
if (lastModel) {
//start could be last center plus half of last column width
start = lastModel.x + lastModel.width / 2;
}
center = start + size * stackIndex + size / 2;
}
return {
size: size,
base: center - size / 2,
head: center + size / 2,
center: center
};
}
For Chart.js you can create a new extension based on the bar class to do this. It's a bit involved though - however most of it is a copy paste of the bar type library code
Chart.types.Bar.extend({
name: "BarAlt",
// all blocks that don't have a comment are a direct copy paste of the Chart.js library code
initialize: function (data) {
// the sum of all widths
var widthSum = data.datasets[0].data2.reduce(function (a, b) { return a + b }, 0);
// cumulative sum of all preceding widths
var cumulativeSum = [ 0 ];
data.datasets[0].data2.forEach(function (e, i, arr) {
cumulativeSum.push(cumulativeSum[i] + e);
})
var options = this.options;
// completely rewrite this class to calculate the x position and bar width's based on data2
this.ScaleClass = Chart.Scale.extend({
offsetGridLines: true,
calculateBarX: function (barIndex) {
var xSpan = this.width - this.xScalePaddingLeft;
var x = this.xScalePaddingLeft + (cumulativeSum[barIndex] / widthSum * xSpan) - this.calculateBarWidth(barIndex) / 2;
return x + this.calculateBarWidth(barIndex);
},
calculateBarWidth: function (index) {
var xSpan = this.width - this.xScalePaddingLeft;
return (xSpan * data.datasets[0].data2[index] / widthSum);
}
});
this.datasets = [];
if (this.options.showTooltips) {
Chart.helpers.bindEvents(this, this.options.tooltipEvents, function (evt) {
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
this.eachBars(function (bar) {
bar.restore(['fillColor', 'strokeColor']);
});
Chart.helpers.each(activeBars, function (activeBar) {
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
});
this.showTooltip(activeBars);
});
}
this.BarClass = Chart.Rectangle.extend({
strokeWidth: this.options.barStrokeWidth,
showStroke: this.options.barShowStroke,
ctx: this.chart.ctx
});
Chart.helpers.each(data.datasets, function (dataset, datasetIndex) {
var datasetObject = {
label: dataset.label || null,
fillColor: dataset.fillColor,
strokeColor: dataset.strokeColor,
bars: []
};
this.datasets.push(datasetObject);
Chart.helpers.each(dataset.data, function (dataPoint, index) {
datasetObject.bars.push(new this.BarClass({
value: dataPoint,
label: data.labels[index],
datasetLabel: dataset.label,
strokeColor: dataset.strokeColor,
fillColor: dataset.fillColor,
highlightFill: dataset.highlightFill || dataset.fillColor,
highlightStroke: dataset.highlightStroke || dataset.strokeColor
}));
}, this);
}, this);
this.buildScale(data.labels);
// remove the labels - they won't be positioned correctly anyway
this.scale.xLabels.forEach(function (e, i, arr) {
arr[i] = '';
})
this.BarClass.prototype.base = this.scale.endPoint;
this.eachBars(function (bar, index, datasetIndex) {
// change the way the x and width functions are called
Chart.helpers.extend(bar, {
width: this.scale.calculateBarWidth(index),
x: this.scale.calculateBarX(index),
y: this.scale.endPoint
});
bar.save();
}, this);
this.render();
},
draw: function (ease) {
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
this.scale.draw(1);
Chart.helpers.each(this.datasets, function (dataset, datasetIndex) {
Chart.helpers.each(dataset.bars, function (bar, index) {
if (bar.hasValue()) {
bar.base = this.scale.endPoint;
// change the way the x and width functions are called
bar.transition({
x: this.scale.calculateBarX(index),
y: this.scale.calculateY(bar.value),
width: this.scale.calculateBarWidth(index)
}, easingDecimal).draw();
}
}, this);
}, this);
}
});
You pass in the widths like below
var data = {
labels: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.7)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 30, 56, 65, 40],
data2: [10, 20, 30, 20, 10, 40, 10]
},
]
};
and you call it like so
var ctx = document.getElementById('canvas').getContext('2d');
var myLineChart = new Chart(ctx).BarAlt(data);
Fiddle - http://jsfiddle.net/moye0cp4/

Google Visualization Column Chart specify Target line as Certainty role

When i put this below code i came with on visualization playground i get the Goal/Target line, but i want it to be dashed/dotted which requires certainty role as specified in the docs. Can anyone enlighten me how to do it with a array input to Google Datatable, or Datatable json string format
Code
function drawVisualization() {
// Create and populate the data table.
var data = google.visualization.arrayToDataTable([
['Year', 'Red', 'Yellow', 'Green','Target'],
['2003', 20, 0, 0,80],
['2004', 0, 55, 0,80],
['2005', 0, 0, 80,80],
['2005', 0, 0, 85,80]
]);
// Create and draw the visualization.
new google.visualization.ColumnChart(document.getElementById('visualization')).
draw(data,
{title:"Yearly Coffee Consumption by Country",
width:600, height:400,
hAxis: {title: "Year"},
legend:'none',
colors:['red','yellow','green'],
//isStacked: true,
series:{
3:{type:'steppedArea',areaOpacity:0}
}
//interpolateNulls: true
}
);
}​
Update
I got it to this level below, with the code but how do i make the line stretch graph width
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Month'); // Implicit domain label col.
data.addColumn('number', 'Sales'); // Implicit series 1 data col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'boolean',role:'certainty'}); // certainty col.
data.addRows([
['Red',20, 0,0, 80,true],
['Yellow', 0, 55, 0, 80,false],
['Green', 0, 0, 85, 80,false]
]);
// Create and draw the visualization.
new google.visualization.ColumnChart(document.getElementById('visualization')).
draw(data,
{title:"Yearly Coffee Consumption by Country",
width:600, height:400,
hAxis: {title: "Year"},
legend:'none',
colors:['red','yellow','green'],
//isStacked: true,
series:{
3:{type:'line',areaOpacity:0}
}
//interpolateNulls: true
}
);
}​
PlayGround:
https://code.google.com/apis/ajax/playground/?type=visualization#column_chart
Roles Docs:
https://developers.google.com/chart/interactive/docs/roles
So what is the right JSON format for dashed lines?
Is there any, i mean anyway i can display a arrow indicator at the right corner of the Target line to visually indicate the Goal?
You can achieve this by creating empty columns at the beginning and end of your chart, and then setting the view window to be within the range that you actually want. The code below achieves this:
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Month'); // Implicit domain label col.
data.addColumn('number', 'Sales'); // Implicit series 1 data col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'number'}); // interval role col.
data.addColumn({type:'boolean',role:'certainty'}); // certainty col.
data.addRows([
['', null, null, null, 80, false],
['Red',20, 0,0, 80,true],
['Yellow', 0, 55, 0, 80,false],
['Green', 0, 0, 85, 80,false],
['', null, null, null, 80, true]
]);
// Create and draw the visualization.
new google.visualization.ColumnChart(document.getElementById('visualization')).
draw(data,
{title:"Yearly Coffee Consumption by Country",
width:600, height:400,
hAxis: {title: "Year"},
legend:'none',
colors:['red','yellow','green'],
//isStacked: true,
series:{
3:{type:'line',areaOpacity:0}
},
hAxis: {
viewWindow: {
min: 1,
max: 4
}
}
//interpolateNulls: true
}
);
}
​

C# SQL Linq get all duplicates

Please tell me how to to solve the problem.
I have to sequences (numbersA and numbersB ). On the output I need only elements that available in the second sequence (numbersB).
int[] numbersA = { 0, 2, 4, 4, 6, 8, 9 };
int[] numbersB = { 2, 4 };
numbersA - numbersB = 2, 4 ,4
Except() or Intersect() are dosen' t work.
It sounds like you want something like:
var result = numbersA.Where(x => numbersB.Contains(x));
That's okay if numbersB is very small, but as it gets larger you'd probably want to change to:
var numbersBSet = new HashSet<int>(numbersB);
var result = numbersA.Where(x => numbersBSet.Contains(x));
Create a HashSet from the second list so lookups are fast, and then just do:
int[] numbersA = { 0, 2, 4, 4, 6, 8, 9 };
int[] numbersB = { 2, 4 };
var set = new HashSet<int>(numbersB);
var finalList = numbersA.Where(n => set.Contains(n));