Change zoom level 3d scatterPlot (Plotly) - javascript

I have a 3d scatterplot of which i want to change its zoom level and pan around it programmatically. I have tried setting the range in the layout from the beggining but it does not change the actual zoom level, just the points in the range:
"layout":
{
margin: {
l: 0,
r: 0,
b: 0,
t: 0,
pad: 1
},
scene:{
xaxis: {range:[-13,13.5]},
yaxis: {range:[-15.5,13.5]},
zaxis: {range:[-14.5,13.5]},
}
},
Also i've tried invoking it with the relayout function, but it is also not working
var update = {
scene:{
xaxis: {range:[-13,13.5]},
yaxis: {range:[-15.5,13.5]},
zaxis: {range:[-14.5,13.5]},
},
};
Plotly.relayout(gd, update);

Finally i found the property to change the camera position:
var update = {
scene:{
camera: {
center: { x: 0, y: 0, z: 0 },
eye: { x: 2, y: 2, z: 0.1 },
up: { x: 0, y: 0, z: 1 }
}
},
};
Plotly.relayout(gd, update);

Related

Bug report: Wrong position of the UIElement / ChartMarkerXY when first rendering a chart with animation disabled

I've tried to place an UIElement / ChartMarkerXY on a chart where the animations are disabled.
Unfortunately, the UIElement / ChartMarkerXY was not in the right position on the first render.
However, when we do an another render (eg: when you put the mouse on the chart for show the AutoCursor), it has been moved to the right position.
I noticed that when the animations are enabled, the first frame of the animation put the UIElement / ChartMarkerXY at the same position.
Currently, I have a workaround for prevent this: chart.engine.renderFrame(0,0)
Demonstration of the bug
You can find in the snippet an example that reproduce the bug:
const {
AxisPosition,
AxisTickStrategies,
emptyLine,
lightningChart,
Point,
UIElementBuilders,
emptyFill
} = lcjs;
const dataSeries = [
{ x: -5, y: 0 },
{ x: 2, y: -5 },
{ x: 5, y: 6 },
{ x: 8, y: 12 },
{ x: 12, y: -12 }
];
const chart = lightningChart().ChartXY({
container: 'chart',
});
chart.setAnimationsEnabled(false);
chart.addLineSeries().add(dataSeries);
chart.addUIElement(UIElementBuilders.TextBox, {
x: chart.getDefaultAxisX(),
y: chart.getDefaultAxisY()
})
.setText('My Text')
.setPosition({ x: 0, y: 0 });
.lcCanvas {
width: 500px;
height: 300px;
}
<script src="https://unpkg.com/#arction/lcjs#3.1.0/dist/lcjs.iife.js"></script>
<h2>Example of the bug</h2>
<div id="chart" class="lcCanvas"></div>
Bug reports should be sent to support#lightningchart.com instead of posting here.
-- Snekw
Bug report sent.
Currently, the workaround I found is chart.engine.renderFrame(0,0).
This will force the re-render of the chart, and put the marker at the right position.
Here, a snippet of how implement the workaround.
const {
AxisPosition,
AxisTickStrategies,
emptyLine,
lightningChart,
Point,
UIElementBuilders,
emptyFill
} = lcjs;
const dataSeries = [
{ x: -5, y: 0 },
{ x: 2, y: -5 },
{ x: 5, y: 6 },
{ x: 8, y: 12 },
{ x: 12, y: -12 }
];
const chart = lightningChart().ChartXY({
container: 'chart',
});
chart.setAnimationsEnabled(false);
chart.addLineSeries().add(dataSeries);
chart.addUIElement(UIElementBuilders.TextBox, {
x: chart.getDefaultAxisX(),
y: chart.getDefaultAxisY()
})
.setText('My Text')
.setPosition({ x: 0, y: 0 });
chart.engine.renderFrame(0, 0); // Workaround: Add this for force the re-render
.lcCanvas {
width: 500px;
height: 300px;
}
<script src="https://unpkg.com/#arction/lcjs#3.1.0/dist/lcjs.iife.js"></script>
<h2>Workaround</h2>
<div id="chart" class="lcCanvas"></div>

Vuex state not updating on mutation

In my Vue.js/Vuex based application I'm using this mutation to reset part of the Vuex state:
restartGame(state) {
state.gameRunning = true
state.camera = {
position: {
x: 0,
y: 10,
z: 0
},
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
velocity: {
x: 0,
z: 0
},
mouseMovement: {
x: 0,
y: 0
},
rotation: {
x: 0,
y: 0
}
}
}
This way, things work out fine, but writing out the whole camera state seems pretty verbose to me. So I extracted the initial camera state into a seperate file:
initialCameraState.js
export default {
position: {
x: 0,
y: 10,
z: 0
},
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
velocity: {
x: 0,
z: 0
},
mouseMovement: {
x: 0,
y: 0
},
rotation: {
x: 0,
y: 0
}
}
I've refactored the resetGame() mutation like this:
import initialCameraState from './initialCameraState'
restartGame(state) {
state.gameRunning = true
state.camera = initialCameraState
}
But somehow this doesn't work, the Vuex store does not get updated but seems to just stay the same. How can this be?
I'm also using initialCameraState.js to set (part of) the initial state of the Vuex store. My first thought was that when mutating the according part of the state, initialCameraState is also being mutated. That would explain resetGame() not showing any effects. So I tried using the object spread operator in both places where initialCameraState.js gets imported/used, but this didn't solve the issue.
I don't have all your code, but here's what I think may be happening. You are initing the game with the initial state which you have imported. During the game you update the state of the object by doing something like:
state.camera['position'] = {
x: 100,
y: 100,
z: 100
}
}
What actually happens is that your initial state has been updated because you have a reference to the object, not a copy of it, so when you try to reset the state it just remains the same, because you have inadvertently changed the initial state object.
To solve this simply wrap the initial state in a function (a factory function) so that the init state always gets returned:
export default function() {
return {
position: {
x: 0,
y: 10,
z: 0
},
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
velocity: {
x: 0,
z: 0
},
mouseMovement: {
x: 0,
y: 0
},
rotation: {
x: 0,
y: 0
}
}
};
Here's a JSFiddle showing what happens without a function (the positions remain the same): https://jsfiddle.net/9qg8ws0x/
And here one with the function (the positions are reset): https://jsfiddle.net/27xozazf/
export default {
initializeCamera () {
return {
position: {
x: 0,
y: 10,
z: 0
},
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
velocity: {
x: 0,
z: 0
},
mouseMovement: {
x: 0,
y: 0
},
rotation: {
x: 0,
y: 0
}
}
}
}
import initial from './initial'
restartGame(state) {
state.gameRunning = true
state.camera = initial.initializeCamera()
}

Matter JS - option list - Am I blind?

New to MatterJS.
In the example, theres is options to draw circle, rectangle, etc.
Those options are like using Sprite, FillStyle...
I see no where in the documentation the list of options and values related to that.
Anyone can help?
Thanks.
From reading the source code of matter.js I found the defaults for options. Doesn't explain what each does but at least here's a list of them:
var defaults = {
id: Common.nextId(),
type: 'body',
label: 'Body',
parts: [],
plugin: {},
angle: 0,
vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
position: { x: 0, y: 0 },
force: { x: 0, y: 0 },
torque: 0,
positionImpulse: { x: 0, y: 0 },
constraintImpulse: { x: 0, y: 0, angle: 0 },
totalContacts: 0,
speed: 0,
angularSpeed: 0,
velocity: { x: 0, y: 0 },
angularVelocity: 0,
isSensor: false,
isStatic: false,
isSleeping: false,
motion: 0,
sleepThreshold: 60,
density: 0.001,
restitution: 0,
friction: 0.1,
frictionStatic: 0.5,
frictionAir: 0.01,
collisionFilter: {
category: 0x0001,
mask: 0xFFFFFFFF,
group: 0
},
slop: 0.05,
timeScale: 1,
render: {
visible: true,
opacity: 1,
sprite: {
xScale: 1,
yScale: 1,
xOffset: 0,
yOffset: 0
},
lineWidth: 0
}
};
As taras pointed out the object's properties are initialized from these options.
These options are body's properties, described in Matter.Body module: http://brm.io/matter-js/docs/classes/Body.html#properties
I think that in those examples, matter.js is handling the drawing of the shapes of the bodies itself through Render.bodies (inside matter.js file) and related functions.
In case anyone want to draw lines, circles or rectangles, they can access the canvas that matter.js uses, and draw them via lineTo, arc functions of canvas, I guess.

Make highcharts bar-chart threshold line visible & labels not to overlap on one another

I have a tornado chart created using bar-charts form Highcharts. I have set a threshold value and on either side of which there are low and high bars.
Now I need to make the threshold line visible. I also have a problem of labels getting overlapped when high, low and base values are equal.
JSFiddle Link: http://jsfiddle.net/xe7qL156/
Please help me to solve it. Thanks.
series: [{
threshold: 29.5,
name: 'Low',
grouping: false,
type: 'bar',
data: [{
x: 0,
y: 12.15,
}, {
x: 1,
y: 15.45,
}, {
x: 2,
y: 31.25,
}, {
x: 3,
y: 12.15,
}],
labels: [10, 5, 1, 2]
}, {
threshold: 29.5,
name: 'High',
grouping: false,
type: 'bar',
data: [{
x: 0,
y: 46.86,
}, {
x: 1,
y: 42.28,
}, {
x: 2,
y: 27.77,
}, {
x: 3,
y: 46.86,
}],
labels: [30, 10, 3, 4]
}]
Update: here is a mockup image of what I need
I'm not 100% sure what you want, but I think you want a vertical line overthe bars at the 29.5 position ?
If so, you can do that with another series:
series: [
{type:'line',color:'black',zIndex:505,data:[[0,29.5],[4,29.5]]},
http://jsfiddle.net/fsbqnw7m/
Alternatively, you can use the renderer API to draw a line wherever you want.
http://api.highcharts.com/highcharts#Renderer
Line can be added also as plotLine in particular place.

Adding data to empty rickshaw chart

I am charting different data with RickshawJS. But I need a way to update the chart when a user clicks the #search button. Right now it just creates a new chart below the old one, and that is pretty messy.
The user enters the page and enters some details and clicks the button to chart it. So ideally I'd like to start with an empty chart that isn't shown, but I can't really figure out how to remove the data from the chart and axes and then update it.
I could call $('#chart svg').remove(); on the chart and axes but it seems messy.
$('#search').click(function(event){
event.preventDefault();
var data = utils.malletData();
var graph = new Rickshaw.Graph( {
element: document.querySelector("#chart"),
width: 800,
height: 250,
series: [ {
name: data['name'],
color: 'steelblue',
data: data['series']
} ]
} );
graph.render();
var hoverDetail = new Rickshaw.Graph.HoverDetail( {
graph: graph,
xFormatter: function(x) {
var date = new Date(x).getTime();
return moment(x).format('MMMM Do YYYY, h:mm:ss a');
},
yFormatter: function(y) { return Math.floor(y) + " users" }
} );
var xAxis = new Rickshaw.Graph.Axis.X( {
graph: graph,
orientation: 'bottom',
element: document.getElementById('x_axis'),
tickFormat: function(x) { return moment(x).fromNow(); },
ticks: 7,
tickSize: 1,
} );
xAxis.render();
var ticksTreatment = 'glow';
var yAxis = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
ticksTreatment: ticksTreatment,
element: document.getElementById('y_axis'),
} );
yAxis.render();
});
There's no official way to do so. However, you could leverage the fact that arrays in javascript are passed by reference and then update the graph.
Have a look at this demo on fiddle
var data = [
{
data: [ { x: 0, y: 120 }, { x: 1, y: 890 }, { x: 2, y: 38 }, { x: 3, y: 70 }, { x: 4, y: 32 } ],
color: "#c05020"
}, {
data: [ { x: 0, y: 80 }, { x: 1, y: 200 }, { x: 2, y: 100 }, { x: 3, y: 520 }, { x: 4, y: 133 } ],
color: "#30c020"
}
];
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'line',
height: 300,
width: 800,
series: data
} );
var y_ticks = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
element: document.getElementById('y_axis'),
} );
graph.render();
$('button#add').click(function() {
data.push({
data: [ { x: 0, y: 200 }, { x: 1, y: 390 }, { x: 2, y: 1000 }, { x: 3, y: 200 }, { x: 4, y: 230 } ],
color: "#6060c0"
});
graph.update();
});

Categories