I want to change following code into node environment. Help me!
code is from http://mapv.baidu.com/examples/
And the content is following:
var map = new BMap.Map(slice.selector, {
enableMapClick: false
}); // 创建Map实例
map.centerAndZoom(new BMap.Point(105.403119, 38.028658), 5); // 初始化地图,设置中心点坐标和地图级别
map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
map.setMapStyle({
style: 'light'
});
var randomCount = 300;
var data = [];
var citys =
["北京","天津","上海","重庆","石家庄","太原","呼和浩特","哈尔滨",
"长春","沈阳","济南","南京","合肥","杭州","南昌","福州","郑州","武汉",
"长沙","广州","南宁","西安","银川","兰州","西宁","乌鲁木齐","成都",
"贵阳","昆明","拉萨","海口"];
// 构造数据
while (randomCount--) {
var cityCenter = mapv.utilCityCenter.getCenterByCityName(citys[parseInt(Math.random() * citys.length)]);
data.push({
geometry: {
type: 'Point',
coordinates: [cityCenter.lng - 2 + Math.random() * 4, cityCenter.lat - 2 + Math.random() * 4]
},
count: 30 * Math.random()
});
}
//数据集
var dataSet = new mapv.DataSet(data);
var options = {
fillStyle: 'rgba(255, 50, 50, 0.6)',
shadowColor: 'rgba(255, 50, 50, 1)',
shadowBlur: 30,
globalCompositeOperation: 'lighter',
methods: {
click: function (item) {
console.log(item);
}
},
size: 5,
draw: 'simple'
}
var mapvLayer = new mapv.baiduMapLayer(map, dataSet, options);
I use "mapv = require('mapv');" to import module mapv. But I can not get module "BMap", how can I get it?
add
in your index.html
and use var BMap = window.BMap in your js code
Related
so i have a phaser group
this.cows = this.physics.add.group({
key: "cow",
repeat: 2,
setXY: { x: 160, y: 1500, stepX: 32 },
});
this.cows.children.iterate(function (child) {
child.setSize(20, 10, true);
child.setBounceY(Phaser.Math.FloatBetween(0.2, 0.4));
});
I plan to update the movement of every child in the update function, so how would i make sure every child has a different amount of movement in a different direction?
Depending on your use case you could simply use, a property destination which the child wants to reach, and when it is reached, just set a new destination.
Here a short demo showcaing this:
(it uses Vector's, not everybody likes/understtands them, but they are concise)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: {
create,
update
},
banner: false
};
function create () {
this.add.text(10,10, 'Random Movment')
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let graphics = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 10);
graphics.generateTexture('cow', 10, 10);
this.cows = this.physics.add.group({
key: "cow",
repeat: 2,
setXY: { x: 50, y: 50, stepX: 32 },
});
this.cows.children.iterate(function (child) {
child.setSize(10, 10, true);
child.setBounceY(Phaser.Math.FloatBetween(0.2, 0.4));
child.speed = Phaser.Math.Between(30, 50);
child.destination = { x: child.x , y: child.y};
});
}
function update(){
this.cows.children.iterate(function (child) {
if(Phaser.Math.Distance.BetweenPoints(child.body.position, child.destination) <= 20){
//new destination
child.destination = { x:Phaser.Math.Between(50, 200), y:Phaser.Math.Between(50, 150)};
// Setup velocity
let vector = new Phaser.Math.Vector2(child.destination);
vector.subtract(child.body.position)
.setLength(child.speed);
child.setVelocity(vector.x, vector.y);
}
});
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
I have a doughnut chart that gets data from an API. The chart displays ok but I can't get the chart data to update, and do that every 2 seconds. I have tried and searched many topics but most are outdated versions of chart.js and my javascript skills are poor.
Chart.js v3.9.1
const totalRunTime = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[1];
const totalTimeRemaining = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[13];
const timeRemaining = ((totalTimeRemaining / totalRunTime) * 100)
// Setup
const datapoints = [(100 - timeRemaining), timeRemaining];
const data = {
datasets: [{
data: datapoints,
backgroundColor: ['rgba(20, 121, 255, 0.7)', 'rgba(208, 208, 208, 0.5)'],
borderWidth: 1,
cutout: '70%'
}]
};
// Counter
const counter = {
id: 'counter',
beforeDraw( chart, args, options ) {
const { ctx, chartArea: { top, right, bottom, left, width, height } } = chart;
ctx.save();
ctx.font = options.fontSize + 'px ' + options.fontFamily;
ctx.textAlign = 'center';
ctx.fillStyle = options.fontColor;
ctx.fillText(datapoints[0].toFixed(3) + '%', width / 2, (height / 2) + (options.fontSize * 0.34));
}
};
// Config
const config = {
type: 'doughnut',
data,
options: {
plugins: {
legend: {
display: false
},
tooltip: {
enabled: false
},
counter: {
fontColor: '#193b68',
fontSize: '16',
fontFamily: 'Sofia Pro Medium'
}
}
},
plugins: [counter]
};
// Render init
const doughnutChart = new Chart(
document.getElementById('doughnutChart'),
config
);
setInterval(function addData(chart, data) {
chart.data.datasets.forEach((dataset) => {
dataset.data = data;
});
chart.update('none');
}, 2000
);
HTML
<canvas id="doughnutChart"></canvas>
It looks like it's not appearing to update because you're calling your data and storing in a variable which, from the scope of the application had not changed.
If you move your data request to a function and then call that from the initialising code and within setInterval you should see your data being updated freshly with each call to the function getData.
Here's a version of your code with what I mean, where getData() is used instead of datapoints:
const getData = () => {
console.log('Requesting data')
const totalRunTime = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[1];
const totalTimeRemaining = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[13];
const timeRemaining = ((totalTimeRemaining / totalRunTime) * 100)
return [(100 - timeRemaining), timeRemaining]
}
const data = {
datasets: [{
data: getData(),
backgroundColor: ['rgba(20, 121, 255, 0.7)', 'rgba(208, 208, 208, 0.5)'],
borderWidth: 1,
cutout: '70%'
}]
};
const counter = {
id: 'counter',
beforeDraw( chart, args, options ) {
const { ctx, chartArea: { top, right, bottom, left, width, height } } = chart;
ctx.save();
ctx.font = options.fontSize + 'px ' + options.fontFamily;
ctx.textAlign = 'center';
ctx.fillStyle = options.fontColor;
ctx.fillText(getData()[0].toFixed(3) + '%', width / 2, (height / 2) + (options.fontSize * 0.34));
}
};
const config = {
type: 'doughnut',
data,
options: {
plugins: {
legend: {
display: false
},
tooltip: {
enabled: false
},
counter: {
fontColor: '#193b68',
fontSize: '16',
fontFamily: 'Sofia Pro Medium'
}
}
},
plugins: [counter]
};
const doughnutChart = new Chart(
document.getElementById('chart'),
config
);
setInterval(function addData(chart, data) {
console.log('updating', Date.now())
doughnutChart.data.datasets.forEach((dataset) => {
dataset.data = getData();
});
doughnutChart.update('none');
}, 2000
);
Here's a codepen of an updating version but with random values used instead of your data requests.
This might be the problem and I hope this helps you.
One tip is to use console.log to see what's being called and placing your code in functions can make it easier to debug too by seeing where and when it is being called by using console.log or debugger.
I have this code that recieves data (wind direction) from an Arduino and this script that shows a compass with the direction. The compass itself works and the data I recieve is correct. The problem is that there is a "wall" at north, so if the wind direction is NW and changes to NE, it doesnt do NW -> N -> NE, it goes like NW -> W -> SW -> S -> SE -> E -> NE
Is there a way to remove this barrier?
CODE FOR COMPASS ITSELF starts at //Kompass
Compass
var socket = io();
socket.on('data', function (data) {
console.log(data);
function safelyParseJSON(json) {
var parsed
try {
parsed = JSON.parse(json)
} catch (e) {
}
return parsed
}
obj = safelyParseJSON(data);
windSpeed = obj.windSpeed;
windDir = obj.windDir;
windFloat = obj.windFloat;
waterAmount = obj.waterAmount;
//Data i tekstform
// document.getElementById('windSpeed').innerHTML = obj.windSpeed;
document.getElementById('windDir').innerHTML = obj.windDir;
document.getElementById('waterAmount').innerHTML = obj.waterAmount;
// Vind-graf
if (chart.data.labels.length != 15) {
chart.data.labels.push(time);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(windSpeed);
});
}
else {
chart.data.labels.shift();
chart.data.labels.push(time);
chart.data.datasets.forEach((dataset) => {
dataset.data.shift();
dataset.data.push(windSpeed);
});
}
chart.update();
});
//Kompas
am5.ready(function () {
var root = am5.Root.new("chartdiv");
root.setThemes([
am5themes_Animated.new(root)
]);
var compassChart = root.container.children.push(
am5radar.RadarChart.new(root, {
panX: false,
panY: false,
startAngle: -90,
endAngle: 270
})
);
var axisRenderer = am5radar.AxisRendererCircular.new(root, {
strokeOpacity: 1,
strokeWidth: 5,
minGridDistance: 10
});
var axis = compassChart.xAxes.push(
am5xy.ValueAxis.new(root, {
maxDeviation: 0,
min: 0,
max: 360,
strictMinMax: true,
renderer: axisRenderer
})
);
axisRenderer.ticks.template.setAll({
forceHidden: true
});
axisRenderer.grid.template.setAll({
forceHidden: true
});
axisRenderer.labels.template.setAll({
forceHidden: true
})
var handDataItem = axis.makeDataItem({
value: 0
});
var hand = handDataItem.set("bullet", am5xy.AxisBullet.new(root, {
sprite: am5radar.ClockHand.new(root, {
radius: am5.percent(99),
topWidth: 5,
bottomWidth: 20,
})
}));
hand.get("sprite").hand.setAll({
fill: am5.color(0xff0000),
fillOpacity: 1
});
axis.createAxisRange(handDataItem);
handDataItem.get("grid").set("visible", false);
handDataItem.get("tick").set("visible", false);
function createLabel(text, value, tickOpacity) {
var axisDataItem = axis.makeDataItem({ value: value });
axis.createAxisRange(axisDataItem);
var label = axisDataItem.get("label");
label.setAll({
text: text,
forceHidden: false,
inside: true,
radius: 20
});
var tick = axisDataItem
.get("tick")
.setAll({
forceHidden: false,
strokeOpacity: tickOpacity,
length: 12 * tickOpacity,
visible: true,
inside: true
});
}
createLabel("N", 0, 1);
createLabel("NE", 45, 1);
createLabel("E", 90, 1);
createLabel("SE", 135, 1);
createLabel("S", 180, 1);
createLabel("SW", 225, 1);
createLabel("W", 270, 1);
createLabel("NW", 315, 1);
for (var i = 0; i < 360; i = i + 5) {
createLabel("", i, 0.5);
}
setInterval(() => {
handDataItem.animate({
key: "value",
to: Math.round(windFloat),
duration: 500,
easing: am5.ease.out(am5.ease.cubic)
});
}, 500);
});
EDIT: I have narrowed it down to something like this:
for (i = 0; i < data.length; i++) {
const newCanvas = document.createElement("canvas");
newCanvas.id = data[i].design_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
createChart([data[i].design_name], [data[i].design_start, data[i].design_end]);
}
With the create chart making the chart id = to the array 'labels':
const myChart = new Chart(
document.getElementById(labels),
config
);
I am attempting to create a tool that creates an 'n' number of charts in ChartJS and save each of them as images. Currently, designButtonClick() sends the 'event_fky' value to
getDesigns(event_fky) in my controller. This method returns all designs with that foreign key. In turn, the chart plots each design on the chart. I need to evolve this into
something that can make a group individual charts for each design based on how many designs there are. My current solution, still conceptual, is to have methods in my controller
create chart variables 'chartData [data here]' and 'labels[datahere]' while looping through the designs returned from getDesigns, and sending those back to the JS script createChart
'n' number of times for each design. It would also send html chart/html element ids based on the design_name attribute to send back to createChart. This way, it is create a unique
chart 'n' number of times.
To save the charts as images, I would use the same set of element ids generated by getDesigns to send the charts to images using JS' toBase64Image() function and saving them to the
user's system.
Is this the best way of solving this problem? Or is this spaghetti, and is there a better method for this? My attempts to find better online answers have only resulted in docs on
updating one chart dynamically, not creating a dynamic number of charts. Much help is appreciated, code is below as well as a screenshot of the current chart output.
JavaScript:
var labels = [];
var cData = [];
function designButtonClick() {
var event_fky = 3;
$.ajax({
url: 'Tree/getDesigns',
type: 'POST',
data: { event_fky }
}).done(function (data) {
for (i = 0; i < data.length; i++) {
labels.push(data[i].design_name);
cData.push([data[i].design_start, data[i].design_end])
}
createChart(labels, cData);
});
}
function createChart(labels, cData) {
const data = {
labels: labels,
datasets: [{
barThickness: 2,
categoryPercentage: .5,
label: 'Design Time',
data: cData,
backgroundColor: [
'rgba(255, 26, 104, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 1,
borderSkipped: false,
borderRadius: 20
}]
};
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: 6000,
ticks: {
stepSize: 1000
}
}
}
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
C# Controller:
public ActionResult getDesigns(int? event_fky)
{
var designs = from e in _context.designs
where (event_fky.HasValue ? e.event_fky == event_fky : e.event_fky == null)
select new
{
design_pky = e.design_pky,
design_name = e.design_name,
design_start = e.design_start,
design_end = e.design_end
};
return this.Json(designs, JsonRequestBehavior.AllowGet);
}
Designs Table:
--------Design--------
design_pky |int
event_fky |int
design_name |varchar
design_start |number
design_end |number
Screenshot of Chart
This is a working answer for the javascript:
var eventList = function () {
var tmp = null;
$.ajax({
'async': false,
url: 'Tree/getEventIDs',
type: 'POST',
data: {},
'success': function (data) {
tmp = data;
}
});
return tmp;
}();
for (var i = 0; i < eventList.length; i++) {
event_fky = eventList[i].event_pky;
event_name = eventList[i].event_name;
event_length = eventList[i].event_end;
var designList = function () {
var tmpi = null;
$.ajax({
'async': false,
url: 'Tree/getDesigns',
type: 'POST',
data: {event_fky},
'success': function (data1) {
tmpi = data1;
}
});
console.log(event_fky);
console.log(tmpi);
return tmpi;
}();
var dLabels = [];
var dLengths = [];
for (var j = 0; j < designList.length; j++) {
dLabels.push(designList[j].design_name);
dLengths.push([designList[j].design_start, designList[j].design_end]);
}
const newCanvas = document.createElement("canvas");
newCanvas.id = event_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
if (dLabels.length != 0) {
createChart(dLabels, dLengths, event_name, event_length);
}
}
}
function createChart(labels, cData, evName, evLen) {
// setup
const data = {
labels: labels,
datasets: [{
barThickness: 4,
categoryPercentage: .5,
label: evName,
data: cData,
backgroundColor: [
'rgba(' + Math.random() * 85 + ', ' + Math.random() * 170 + ', ' + Math.random() * 255 + ', 1)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 0,
borderSkipped: false,
borderRadius: 20
}]
};
// config
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: evLen,
ticks: {
stepSize: 100
}
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById(evName),
config
);
return myChart;
}
I want to place the text my data values at the center of the chart js donut charts, I don't know how to do that, I checked the chart js official docs, but they didn't provide any information about this, how can I achieve this.
Here is my code:
HTML:
<canvas id="gx_150s_658Ed8745321" width="200" height="120"></canvas>
JS:
var randomScalingFactor = function () {
return Math.round(Math.random() * 100);
};
var gx_150s_658Ed8745321_ctx = document.getElementById('gx_150s_658Ed8745321').getContext('2d');
var gx_150s_658Ed8745321 = new Chart(gx_150s_658Ed8745321_ctx, {
type: 'doughnut',
data: {
labels: ['Utilized', 'Balence'],
datasets: [{
label: 'Utilized',
data: [95, 5],
backgroundColor: [
'rgb(0, 153, 0, 0.7)',
],
borderColor: [
'rgba(54, 162, 235, 2)',
],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
title: {
display: true,
text: ' Utilized : 95 %'
},
animation: {
animateScale: true,
animateRotate: true
},
}
});
Expected output:
I'm using a simple plug-in:
config = {
options: {
//...
}
//...
plugin: [{
id: 'my-doughnut-text-plugin',
afterDraw: function (chart, option) {
let theCenterText = "50%" ;
const canvasBounds = canvas.getBoundingClientRect();
const fontSz = Math.floor( canvasBounds.height * 0.10 ) ;
chart.ctx.textBaseline = 'middle';
chart.ctx.textAlign = 'center';
chart.ctx.font = fontSz+'px Arial';
chart.ctx.fillText(theCenterText, canvasBounds.width/2, canvasBounds.height*0.70 )
}
}];
}
You still need to calculate what you wan't in the center text (variable theCenterText).
we can use the animation onComplete callback to know when the animation has finished.
then we can calculate the size and placement of the canvas,
and position a label in the center of the canvas.
animation: {
animateScale: true,
animateRotate: true,
onComplete: function() {
var canvasBounds = canvas.getBoundingClientRect();
dataLabel.innerHTML = ' Utilized : 95 %';
var dataLabelBounds = dataLabel.getBoundingClientRect();
dataLabel.style.top = (canvasBounds.top + (canvasBounds.height / 2) - (dataLabelBounds.height / 2)) + 'px';
dataLabel.style.left = (canvasBounds.left + (canvasBounds.width / 2) - (dataLabelBounds.width / 2)) + 'px';
}
},
see following working snippet...
$(document).ready(function() {
var randomScalingFactor = function () {
return Math.round(Math.random() * 100);
};
var canvas = document.getElementById('gx_150s_658Ed8745321');
var dataLabel = document.getElementById('data-label');
var gx_150s_658Ed8745321_ctx = canvas.getContext('2d');
var gx_150s_658Ed8745321 = new Chart(gx_150s_658Ed8745321_ctx, {
type: 'doughnut',
data: {
labels: ['Utilized', 'Balence'],
datasets: [{
label: 'Utilized',
data: [95, 5],
backgroundColor: [
'rgb(0, 153, 0, 0.7)',
],
borderColor: [
'rgba(54, 162, 235, 2)',
],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
animation: {
animateScale: true,
animateRotate: true,
onComplete: function() {
var canvasBounds = canvas.getBoundingClientRect();
dataLabel.innerHTML = ' Utilized : 95 %';
var dataLabelBounds = dataLabel.getBoundingClientRect();
dataLabel.style.top = (canvasBounds.top + (canvasBounds.height / 2) - (dataLabelBounds.height / 2)) + 'px';
dataLabel.style.left = (canvasBounds.left + (canvasBounds.width / 2) - (dataLabelBounds.width / 2)) + 'px';
}
},
}
});
});
#data-label {
font-size: 20px;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<canvas id="gx_150s_658Ed8745321" width="200" height="120"></canvas>
<span id="data-label"></span>