vis.js network fit function - javascript

I am using vis.js 4.16.1 to draw the network graphs. Currently I have two network graphs. One network graph for the user drawing. After the user has done, I want to copy exactly whatever the network graph is to the second network graph. However, I can't set the same viewpoint as the first one. This is the options for the first network:
options = {
locale: 'en',
physics: {
"enabled": false,
},
edges: {
smooth: {
type: 'continuous'
}
},
interaction: {
navigationButtons: true,
selectConnectedEdges: false
}
};
I have disabled the physics to allow the user organize the node themselves.
This is the options for the second network:
var options = {
locale: 'en',
physics: {
"enabled": false
},
edges: {
smooth: {
type: 'continuous'
}
},
interaction: {
dragNodes: false,
dragView:true
}
};
When I use the fit function (http://www.cse.unsw.edu.au/~mike/myrlibrary/visNetwork/doc/network/)
var fitOption = {
nodes: nodes.getIds() //nodes is type of vis.DataSet contains all the nodes
}
secondNetwork.fit(fitOption);
There is nothing changed.
When I use the moveTo function:
var centerOptions = {
position: {
x: firstNetwork.getViewPosition().x,
y: firstNetwork.getViewPosition().y},
}
}
secondNetwork.moveTo(centerOptions);
Still, I can't move my canvas to the point where the first network focused on. The canvas is not moving at all.
Could someone give me some suggestions? Thanks in advance,

Thanks Reiner, I have figure out the reason why fit() and moveTo() function are not working in my context, I need set the option:
physics: {
"enabled": true
}
otherwise it's not working. What did is before I call my fit() function, change enabled to true, call fit() function, then set enabled to false.

You can use network.fit(), this will do the same as the upper button in the right-bottom corner. So all nodes will be focused.
You can use the Dataset-object for nodes and edges, than it its rather easy to copy all the nodes and edges to the same xy-coordinates with
var xy = network1.edges.get();
network2.edges.add(xy);

Related

How do I disable the export menu in amCharts

For one of our charts, we load it in batches, which could take a while. We'd like to disable the export menu (i.e., not allow it to open when the user clicks it) while the batches are loaded and enable it again once the last batch is in the chart. How does one go about doing that? Ideally, some indication that it's disabled (e.g., dimming, grey text) would also be nice to have.
For further info, the code for creating the menu is something along these lines:
chart.exporting.menu = new am4core.ExportMenu();
chart.exporting.menu.items = [
{
label: "...",
menu: [
{
type: "custom",
label: "CSV",
title: "Download CSV,
options:
{
callback: function()
{
// function for downloading CSV data
}
}
}]
}];
if (needPrintOption)
{
chart.exporting.menu.items[0].menu.push(
{
label: "Print",
title: "Print Chart",
type: "custom",
options:
{
callback: function()
{
// function to print chart contents
}
}
});
}
The menu is created when the chart is created. Essentially, I want the top level (labeled "...") to be disabled (ideally with some visual indication) while the chart is loading or being updated. (I don't want to have to create and destroy the menu, as we do have a live mode where the data in the chart is added to periodically. It would be less jarring for the user, visually, to disable the menu when I don't want user interaction with it and re-enable it when user interaction is allowed.)
You can use ready event:
chart.events.on('ready', () => {
chart.exporting.menu = new am4core.ExportMenu();
});

How can I use props as option data of Echarts in a Vue 3 component?

So I have been trying to make a linechart work with Echarts. I made this LineChart.vue and expect it to get props, which are arrays, from its father component as options data of Echarts.
But the props, which are proxies of arrays, doesn't seem to work well. It is shown in the console that it has the right target, but this proxy is not recognized by Echarts, so there was no data on my chart.
And to make it wierder to me, I accidently found out that if I keep my terminal open, make some changes to the code (which is nothing but comment and uncomment the same lines), and save it (which probably rerends this component), the props somehow works and the linechart actually shows up! But if I refresh the page, the data goes blank again.
Here is my code:
<template>
<div id="chart"></div>
</template>
<script>
let chart;
export default {
data() {
return {
option: {
name: "demo",
xAxis: {
type: "category",
data: [],
},
yAxis: {
// type: "value",
},
series: [
{
data: [],
type: "line",
},
],
},
};
},
props: {
xAxisData: Array,
seriesData: Array,
},
methods: {
initChart() {
chart = this.$echarts.init(document.getElementById("chart"));
// these are the four lines that I commented and uncommented to make things wierd
this.option.xAxis.data = this.xAxisData;
this.option.series[0].data = this.seriesData;
console.log(this.option.xAxis.data);
console.log(this.option.series[0].data);
chart.setOption(this.option);
},
},
mounted() {
this.initChart();
},
watch: {
xAxisData: {
handler: function (newData) {
this.option.xAxis.data = newData;
},
deep: true,
},
seriesData: {
handler: function (newData) {
this.option.series[0].data = newData;
},
deep: true,
},
},
};
</script>
<style scoped>
#chart {
height: 250px;
width: 400px;
}
</style>
And here iswhat is the proxy like before and after I made some minor changes to the code
I also tried to turn this proxy xAxisData into an object using Object.assign(), but it turns out to be empty! I am starting to think that it might have somthing to do with component life cycle, but I have no clue when and where I can get a functional proxy. Can someone tell me what is actually going on?
FYI, here are value of props in console and value of props in vue devtool.
Just figured it out. Just so you know, the info provided above was insufficient, and I made a noob move.
My vue component was fine, it was async request that caused this problem. The data for my Echarts props is requseted through a Axios request, and my child-component (the linechart) was rendered before I got the data. Some how, the proxies of the arrays donot have the data, yet they got the target shown right. By the time my child-component got the right data, the Echart was already rendered with outdated options data, which by the way was empty. And that is why re-render it can show us the data. It has nothing to do with proxy, proxy works just fine. It is me that needs to pay more attention to aysnc movement. Also, I learned that obviously Echarts was not reactive at all, so I watched the props and updated the option like this:
watch :{
xAxisData: {
handler: function (newData) {
this.option.xAxis.data = newData;
this.chart.clear();
this.chart.setOption(this.option);
},
deep: true,
},
}
It works.

Got 'IndexSizeError' with IE 11/Edge on large images with Openseadragon

I am using Openseadragon to display large images, and with some of them I got "SCRIPT5022: IndexSizeError" error message with IE 11 and Edge.
It work with small image (1024 x 656 pixels), but fails with any larger image (2981 x 4123 for example). Any other browser works fine in all cases.
I am using 'legacy-image-pyramid' type source.
My Openseadragon configuration :
viewer = OpenSeadragon({
id: 'openseadragon',
toolbar: 'viewer-toolbar',
maxZoomLevel: 5,
minZoomLevel: 0,
preload: true,
sequenceMode: false,
tileSources: SOURCE,
crossOriginPolicy: 'Anonymous',
// buttons
zoomInButton: 'zoom-in',
zoomOutButton: 'zoom-out',
showRotationControl: true,
rotateLeftButton: 'rotate-left',
rotateRightButton: 'rotate-right',
homeButton: 'home',
showFullPageControl: false,
rotateleftButton: 'rotate-left',
rotaterightButton: 'rotate-right',
// gestures
gestureSettingsMouse: {
clickToZoom: false,
dblClickToZoom: true,
pinchToZoom: true,
pinchRotate: true
},
gestureSettingsTouch: { pinchRotate: true }
});
Source code of larges images (fail) :
var SOURCE = [
{
type: 'legacy-image-pyramid',
levels: [{
url: 'https://rgw.atolcd.com/swift/v1/sillon_container_test/entrepot/B574636101_Prev36_18930411_0001.jpg',
height: 4123,
width: 2981
}]
}
];
Source code of smaller image (work) :
var SOURCE = [
{
type: 'legacy-image-pyramid',
levels: [{
url: 'https://rgw.atolcd.com/swift/v1/sillon_container_test/entrepot/carte1.jpg',
height: 656,
width: 1024
}]
},
];
I found this issue ( https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/16192680/ and IndexSizeError on drawImage on IE and Edge with IE11/Edge (get fixed in recent version of Edge apparently) if drawImage parameters are wrong, but OpenSeadragon's values are good. (and works with small images, so it should work with any image ?).
I tried another source type (image tile source), but same error.
It works if I disable canvas and use img instead (with useCanvas: false in Options), but this is not a solution for me (it breaks my viewer implementation).

Vue.js - Highmaps - change variable's value from inside chart

First of all let me introduce you to my project. I am desining a web application that will show some data about devices scattered around a country. To create this I used Vue.js and HighCharts (HighMaps for the map part). This is the result I have achieved now.
What I want to add now is the possibility for the end-user to click on a marked region and show all of the devices in that region. To do that I need the region's "ID", called code in HighMaps, to send a ajax request to my db and I would also like to make this new "div" a component so that I can use it freely in my application. I'll put a sketch image of what I mean (excuse me for my really bad paint skills :D):
The black lines are not important, what I would like to achieve is to show a new component besides the map (or wherever really). Next is my current code, I am using the one page, one component style so both template and script tags are in the same file and I omitted in the script tag all the unecessary things. Right now I just set up a div with curly brackets to update a variable on change, just to debug more easily. My main problem is that, in the plotOptions.series.point.events.click when I try to reference the this.foo variable it doesn't set it since the div doesn't update. I think that might be a scope issue but I wouldn't know where to start looking.
<template>
<div id="canvasContainer">
<highmaps :options="chartOptions"></highmaps>
<app-componentForDevices><app-componentForDevices>
<div>{{foo}}</div>
</div>
</template>
<script>
import HighCharts from 'vue-highcharts';
import json from '../map.json'
export default {
data: function () {
return {
foo: 'NO',
/* Map */
chartOptions: {
chart: {
map: json, // The map data is taken from the .json file imported above
},
plotOptions: {
series: {
point: {
events: {
click: function () {
this.foo='OK'
}
}
}
},
map: {
joinBy: ['hc-key', 'code'],
allAreas: false,
tooltip: {
headerFormat: '',
pointFormat: '{point.name}: <b>{series.name}</b>'
},
}
},
/* Zoom and move */
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
series: [
{
allAreas: true,
showInLegend: false,
},
{
borderColor: '#a0451c',
cursor: 'pointer',
name: 'ERROR',
color: "red",
data: ['it-na', 'it-mi', 'it-mo', 'it-ud'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#a09e21',
cursor: 'pointer',
name: 'WARNING',
color: "yellow",
data: ['it-ts', 'it-av', 'it-ri'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#4ea02a',
cursor: 'pointer',
name: "OK",
color: "lightgreen",
data: ['it-pa', 'it-ve', 'it-bo', 'it-ta', 'it-pn'].map(function (code) {
return {code: code};
}),
},
],
}
}
}
}
</script>
<style scoped>
svg{
align-items: center;
}
Thanks in advance for the help. Cheers!
EDIT
I have just tried #icecream_hobbit 's suggestion and using a ECMA6 arrow function helped since now I can access the variable store in Vue but now I lost the access to the local arguments like this.name which made possibile for me to print the selected region. Any ideas? Am I missing something?
EDITv2
Thanks to #icecream_hobbit I have found a way to do what I wanted. You just need to add an object inside the parenthesis so that you can use this for the global variable and e for your mouse click event.
events: {
click: (e) => {
this.foo = 'OK'
this.foo = e.point.name
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Until arrow functions, every new function defined its own this value
(a new object in the case of a constructor, undefined in strict mode
function calls, the base object if the function is called as an
"object method", etc.)
The this you were accessing did not belong to the Vue instance. You can use an arrow function () => {/*function body*/} to inherit the this of the Vue instance.
An arrow function expression has a shorter syntax than a function
expression and does not have its own this, arguments, super, or
new.target.
EDIT: For the added question of how do I do I get the Vue instance, and the object instance at the same time you can use a closure.
click: function(VueInstance){
return function() {
VueInstance.Foo = 'OK';
}(this)
}

Highmaps: how do I detect the target of enableDoubleClickZoomTo?

I have a map of the United States rendered in Highmaps, with enableDoubleClickZoomTo set to true. I've gotten stuck trying to discern what state a user has double clicked on to zoom the map, and wondered if there was information buried in the redraw event that would help me calculate this.
Here's a fiddle of the issue: http://jsfiddle.net/tjnicolaides/x8q1d1cs/
$('#container').highcharts('Map', {
chart: {
events: {
redraw: function (event) {
console.log(event);
console.log(this.getSelectedPoints());
}
}
},
mapNavigation: {
enabled: true,
enableDoubleClickZoomTo: true
},
series: [{
data: data,
mapData: Highcharts.maps['countries/us/us-all'],
joinBy: 'hc-key',
allowPointSelect: true,
states: {
hover: {
color: '#BADA55'
},
select: {
color: 'purple'
}
}
}]
});
When I console.log event after double clicking on a state, I'm getting a large object with information about the state of the entire chart.
If I single click to select a state, and then double click to zoom in on it, I get information about the state from this.getSelectedPoints() - however, it is not reasonable to expect that anything will be selected prior to zooming. In some maps, it may be disabled altogether. I included it here as a demonstration of the type of output I was originally hoping to get from redraw. Calculating a postal code, state name, or index to filter the original series with would be acceptable.
I think the easiest way to detect that point by wrapping Pointer.onContainerDblClick, like this:
(function (H) {
H.wrap(H.Pointer.prototype, "onContainerDblClick", function (p, event) {
console.log(this.chart.hoverPoint); // hovered point - may not exist, e.g. when clicking on the blank space
p.call(this, event);
});
})(Highcharts)
And live demo: http://jsfiddle.net/x8q1d1cs/8/

Categories