I've created a layer in 3D that render and works perfectly.
I want to create a HexagonLayer where his elevation will be based on SUM of all volumes that I think I'm doing correctly.
But I don't know do that size scale should by log as you can see in kepler image.
How can work with log size scale??
Here is my code:
const BLUE_COLORS = [
[230, 250, 250],
[193, 229, 230],
[157, 208, 212],
[117, 187, 193],
[75, 167, 175],
[0, 147, 156],
];
const material = {
ambient: 0.64,
diffuse: 0.6,
shininess: 32,
specularColor: [51, 51, 51],
};
class DeckGLOverlay extends Component {
constructor(props) {
super(props);
this.state = {
x: null,
y: null,
hoveredObject: null,
id: uuidv4(),
};
}
getCoordinates = () => {
let coordinates = [];
const { data3d } = this.props;
data3d.forEach(supplypoint => {
if (
!supplypoint.geojson ||
(supplypoint.geojson &&
supplypoint.geojson &&
!supplypoint.geojson.coordinates)
) {
return;
}
let feature = {
COORDINATES: supplypoint.geojson.coordinates,
VOLUME: supplypoint.value,
UNITS: supplypoint.units,
DATA: {
supplypointId: supplypoint.supplypointId,
address: supplypoint.address,
client: supplypoint.client,
diameter: supplypoint.diameter,
endusetype: supplypoint.endusetype,
usetype: supplypoint.usetype,
},
};
coordinates.push(feature);
});
return coordinates;
};
sumElevations = values => {
if (values.length >= 1) {
let totalVolumes = 0;
for (let item of values) {
if (item.hasOwnProperty("VOLUME")) {
totalVolumes += item["VOLUME"];
}
}
return totalVolumes;
}
return 0;
};
render() {
const { viewport } = this.props;
const layers = [];
if (this.props.data3d) {
layers.push(
new HexagonLayer({
id: `hexagon-layer-${uuidv4()}`,
data: this.getCoordinates(),
pickable: true,
extruded: true,
material: material,
radius: 5,
elevationRange: [0, 1000],
elevationScale: 1,
elevationAggregation: "SUM",
colorRange: BLUE_COLORS,
colorScaleType: "quantile",
colorAggregation: "SUM",
getPosition: d => d.COORDINATES,
getElevationValue: d => this.sumElevations(d),
})
);
}
return (
<DeckGL layers={layers} onHover={this.onHoverDeckgl} viewState={viewport} />
);
}
}
export default injectIntl(DeckGLOverlay);
Image
I've used scaleLag from d3-scale, from d3-scale library.
Solution:
class DeckGLOverlay extends Component {
constructor(props) {
super(props);
this.state = {
x: null,
y: null,
hoveredObject: null,
id: uuidv4(),
};
this.rangeColor = null;
this.logScale = scaleLog()
.domain([10, 100000])
.range([0, 500]);
}
getCoordinates = () => {
...
return coordinates;
};
sumElevations = values => {
if (values.length >= 1) {
let totalVolumes = 0;
for (let item of values) {
if (item.hasOwnProperty("VOLUME")) {
totalVolumes += item["VOLUME"];
}
}
return totalVolumes;
}
return 0;
};
elevationByLogScale = values => {
let totalVolumes = this.sumElevations(values);
let scale = parseInt(this.logScale(totalVolumes));
if (isNaN(scale)) return 0;
return scale;
};
render() {
const { viewport } = this.props;
const layers = [];
if (this.props.data3d) {
layers.push(
new HexagonLayer({
id: `hexagon-layer-${uuidv4()}`,
data: this.getCoordinates(),
pickable: true,
extruded: true,
radius: 5,
elevationRange: [0, 500],
elevationScale: 1,
colorRange: BLUE_COLORS,
getPosition: d => d.COORDINATES,
getElevationValue: d => this.elevationByLogScale(d),
})
);
}
return (
<DeckGL layers={layers} viewState={viewport} />
);
}
}
Related
To show all bars I have set the horizontal scrolling to chartjs in Ionic angular project , and i have used the DataLabelsPlugin constant for bars label. and while scrolling the datalabels is overlapping with y-axis its not hiding before y-axis like bars.
and also horizontal scroll is not happening smoothly.
graph working fine as a expected output
marked with issue about - after scrolling the datalabels went over the y-axis not hide below y-axis like bars
I have tried to add and used the custom datalabels but same issue i am getting and i didnt find any css or attribute on 'https://www.chartjs.org/docs/latest/' official site or not on any other sites -> to hide the datalabels from over the y-axis.
ts file code:
createBarChart() {
const footer = (tooltipItems) => {
let sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return this.util.getFormatValue(sum)+'%';
};
const toolLabel = (tooltipItems) => {
return "";
};
const toolTitle = (tooltipItems) => {
var string_to_array = function (str) {
return str.trim().split("#$#$");
};
var ss;
tooltipItems.forEach(function(tooltipItem) {
ss = string_to_array(tooltipItem.label.replace(/(.{40})/g, "$1#$#$"))
});
return ss;
};
let graphSize = Math.max(...this.daywise_occupancy);
if(graphSize == 0){
graphSize =1;
}
const plugin = {
id: 'customCanvasBackgroundColor',
beforeDraw: (chart, args, options) => {
const {ctx} = chart;
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, chart.width, chart.height);
ctx.restore();
}
};
this.bars = new Chart(this.barchart6.nativeElement, {
type: 'bar',
data: {
labels: this.daywise_date,
datasets: [{
data: this.daywise_occupancy,
backgroundColor: function(context) {
var value = context.dataset.data[context.dataIndex];
return value <= 15 ? '#f95959'
: value > 15 && value <=60 ? '#F5A623'
: '#00ADB5'
},
borderColor: function(context) {
var value = context.dataset.data[context.dataIndex];
return value <= 15 ? '#f95959'
: value > 15 && value <=60 ? '#F5A623'
: '#00ADB5'
},
borderWidth: 1,
barThickness:30,
}]
},
plugins: [DataLabelsPlugin,plugin],
options: {
animations: {
tension: {
duration: 1000,
easing: 'linear',
from: 1,
to: 0,
loop: true
}
},
scales: {
x: {
min:0,
max:5,
ticks : {
maxRotation: 70,
minRotation: 70,
font:{
size:10,
},
callback: function(value : any, index, ticks_array) {
let characterLimit = 12;
let label = this.getLabelForValue(value);
if ( label.length >= characterLimit) {
return label.slice(0, label.length).substring(0, characterLimit -1).trim() + '..';
}
return label;
}
}
},
y: { // defining min and max so hiding the dataset does not change scale range
min: 0,
max: this.loader.getGraphsizeRound(graphSize),
title: { display: true, text: (this.titleSet)? '% of Branches Contribution' : '% of Seat Occupancy' },
beginAtZero: true,
display: true,
position: 'left',
// ticks: {
// stepSize: 6,
// },
}
},
plugins: {
legend: {
display: false
},
datalabels:{
anchor: 'end',
align: 'end',labels: {
value: {
color: '#2C3A45;',
formatter: function (value) {
// return Math.round(value) + '%';
return value + '%';
},
font:{
weight:700,
size:14
}
}
}
},
tooltip: {
callbacks: {
footer:footer,
label: toolLabel,
title:toolTitle
},
displayColors:false
}
}
}
});
this.bars.canvas.addEventListener('touchmove',(eve) => {
this.touchmove(eve,this.bars)
});
this.bars.canvas.addEventListener('touchstart',(eve) => {
this.touchstart(eve)
});
}
touchstart(e)
{
this.startX = e.touches[0].clientX;
this.startY = e.touches[0].clientY;
}
touchmove(e,chart)
{
var deltaX = e.touches[0].clientX - this.startX,
deltaY = e.touches[0].clientY - this.startY;
const dataLength = chart.data.labels.length;
let min = chart.options.scales.x.min;
if(deltaX < 0){
if( chart.options.scales.x.max >= dataLength ){
chart.options.scales.x.min = dataLength - 5;
chart.options.scales.x.max = dataLength;
}else{
chart.options.scales.x.min += 1;
chart.options.scales.x.max += 1;
}
// console.log( chart.options.scales.x.min);
// chart1line.options.scales.y.max = graphSize
}else if(deltaX > 0){
if( chart.options.scales.x.min <= 0 ){
chart.options.scales.x.min = 0;
chart.options.scales.x.max = 4;
}else{
chart.options.scales.x.min -= 1;
chart.options.scales.x.max -= 1;
}
}else{
}
chart.update();
}
HTML code:
<div class="chartWrapper">
<div class="chartAreaWrapper">
<canvas #barchart6 height="190" max-height="190" width="0"></canvas>
</div>
</div>
My expected output
horizontal scroll work smoothly.
after scrolling label should not overlap on y-axis.
I have been learning Google Charts using examples on here and have created a line chart in which I can toggle series on and off by clicking them in the legend.
I would also like to alternate between solid and dashed lines for each series. However the lineDashStyle option isn't working and I can't see why. Can anyone help please?
google.charts.load('current', {'packages': ['corechart', 'table']});
var dataValues = [{DateScore: '2018-6-14', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-15', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-17', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-22', A: 800, B: 600, C: 1000, D: 900, E: 300, F: 100, NrS: 600, } ];
var Data = {
displayed: [...dataValues],
hidden: Object.keys(dataValues[0]).reduce((a, c) => {
a[c] = false;
return a;
}, {}),
map: Object.keys(dataValues[0])
};
google.charts.setOnLoadCallback(DrawChartScores);
function DrawChartScores() {
var data = new google.visualization.DataTable();
var options = {
title: 'Scores',
width: '80%',
height: '80%',
colors: ['ff0000','ff0000','000099','000099','ff6600','ff6600','006600'],
series: {
1: { lineDashStyle: [4, 2] },
3: { lineDashStyle: [4, 2] },
5: { lineDashStyle: [4, 2] },
},
explorer: {
keepInBounds: true,
actions: ['dragToZoom', 'rightClickToReset']
},
series: Data.map.reduce((a, c, i) => {
a[i] = {};
return a;
}, {})
};
data.addColumn('date', 'Day');
data.addColumn('number', 'A');
data.addColumn('number', 'B');
data.addColumn('number', 'C');
data.addColumn('number', 'D');
data.addColumn('number', 'E');
data.addColumn('number', 'F');
data.addColumn('number', 'NrS');
for (var i = 0; i < dataValues.length; i++) {
let newRow = Object.values(dataValues[i]);
newRow[0] = new Date(newRow[0]);
data.addRow(newRow);
}
var chart = new google.visualization.LineChart(document.getElementById('chartP'));
var last = {
column: true,
row: true
};
function showHideSeries() {
var sel = chart.getSelection();
if (sel.length === 0 && last.row === null) {
Data.hidden[Data.map[last.column]] = !Data.hidden[Data.map[last.column]];
} else if (sel.length && sel[0].row === null) {
// toggle the current item selected
Data.hidden[Data.map[sel[0].column]] = !Data.hidden[Data.map[sel[0].column]];
last = sel[0];
} else {
return;
}
vparse(data);
options = vkillLegend(options);
chart.draw(data, options);
}
google.visualization.events.addListener(chart, 'select', showHideSeries);
chart.draw(data, options);
}
function vparse(data) {
Data.displayed.reduce((a, c, i) => {
for (let k in c) {
if (k === "DateScore") continue;
if (Data.hidden[k])
data.setValue(i, Data.map.indexOf(k), null);
else
data.setValue(i, Data.map.indexOf(k), c[k]);
}
return true;
}, []);
return data;
}
function vkillLegend(options) {
options.series = Object.keys(options.series).reduce((a, c, i) => {
let current = {};
if (Data.hidden[Data.map[i]]) current.color = "#CCCCCC";
else c.color = null;
a[i - 1] = current;
return a;
}, {});
return options;
}
The resulting graph looks like this - all the lines are solid:
Graph without dashed lines
Moving the map doesn't move the icons with it, instead the icons stay fixed to the same position on the page.
My icons get added to the correct latitude and longitude on my map. However, when I drag the map, the icons stay fixed on the same position on the page and are no longer being displayed at the correct latitude and longitude.
let sMap;
let ciLayer;
let neutralMarkers = [];
let gVesselIcons = {};
let numOfVessels = 0;
let ROI;
let nwLat;
let nwLon;
let seLat;
let seLon;
window.indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB;
//prefixes of window.IDB objects
window.IDBTransaction =
window.IDBTransaction ||
window.webkitittIDBTransaction ||
window.msIDBTransaction;
window.IDBKeyRange =
window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
let db;
const [dbPromise, dbResolve, dbReject] = (() => {
let resolve, reject;
return [
new Promise((res, rej) => {
resolve = res;
reject = rej;
}),
resolve,
reject
];
})();
let dbGSTSStore = window.indexedDB.open('GSTSStore', 1);
let dbVessels;
let dbTransactions;
let dbMessages;
dbGSTSStore.onerror = function(event) {
dbReject();
console.log('error: ');
};
dbGSTSStore.onsuccess = function(event) {
dbResolve();
db = dbGSTSStore.result;
};
dbGSTSStore.onupgradeneeded = function(event) {
const db = event.target.result;
dbVessels = db.createObjectStore('vessels', {
keyPath: 'mmsi'
});
dbMessages = db.createObjectStore('messages', {
keyPath: 'id'
});
dbTransactions = db.createObjectStore('transactions', {
keyPath: 'id'
});
};
async function InitializeSimple(
pBuildNumber,
pSysPersonId,
pSysOrganizationId
){
await GetOrganizationPrefs(pSysOrganizationId);
await GetPersonPrefs(pSysPersonId);
SetLabelText('lblBuildNumber', `Build: ${pBuildNumber}`);
dragElement(document.getElementById("vessel-info"));
nwLat = gOrganizationPrefs.roinwse.nwlat || gPersonPrefs.aoi.nwlat;
nwLon = gOrganizationPrefs.roinwse.nwlon || gPersonPrefs.aoi.nwlon;
seLat = gOrganizationPrefs.roinwse.selat || gPersonPrefs.aoi.selat;
seLon = gOrganizationPrefs.roinwse.selon || gPersonPrefs.aoi.selon;
try {
sMap = L.map('map-content', {
fullscreenControl: false,
zoomControl: false,
zoom: 6,
attributionControl: false,
preferCanvas: true
}).setView([19, 55]);
ciLayer = L.canvasIconLayer({}).addTo(sMap);
L.tileLayer(MapUrl[0], {
attribution: MapAttribution[0],
zoom: 5,
minZoom: 4,
maxNativeZoom: 13,
maxZoom: 20
}).addTo(sMap);
}
catch (error) {
console.log("error initializing map\n");
}
// SetVesselUpdate();
if(gOrganizationPrefs) await SetROI(gOrganizationPrefs.roinwse);
else await SetROI(gPersonPrefs.aoi);
await CreateNeutralLayer();
}
function SetLabelText(pLabel, pText) {
const lLabel = document.getElementById(pLabel);
if (lLabel !== undefined) lLabel.textContent = pText;
}
function CreateNeutralLayer(){
return new Promise((resolve, reject) => {
try {
const lTransaction = db.transaction(['vessels'], 'readonly');
let vessels = lTransaction.objectStore('vessels');
const countRequest = vessels.count();
countRequest.onsuccess = function() {
numOfVessels = countRequest.result;
}
vessels.openCursor().onsuccess = function(e) {
let cursor = e.target.result;
if (cursor !== null) {
let value = cursor.value;
let latitude = value.lat;
let longitude = value.lon;
let canInclude = checkROIBoundaries(latitude, longitude);
if (canInclude && cursor.value !== undefined) {
AddToLayers(cursor.value);
}
cursor.continue();
}
}
resolve('OK');
}
catch (err) {
console.log("error is: ", err, "\n");
reject({ error: err, function: 'CreateNeutralLayer()'});
}
});
}
function AddToLayers(vessel) {
let vesselRotationDegree = vessel.headingdegree.toString().padStart(2, '0');
if (vesselRotationDegree == '32') vesselRotationDegree = '00';
let vesselIconType = 'type-3';
let gBaseRiskIconURL = `./public/img/vessel/${vesselIconType}/vessel-`;
let gBaseRiskNeutralUrl = `${gBaseRiskIconURL}neutral-`;
var vIcon = L.icon({
iconUrl: `${gBaseRiskNeutralUrl}${vesselRotationDegree}.svg`,
iconSize: [24, 24],
iconAnchor: [24, 24]
});
const marker = L.marker([vessel.lat, vessel.lon], { icon: vIcon});
marker.properties = {
vesselname: vessel.shipname,
mmsi: vessel.mmsi,
imo: vessel.imo,
lat: vessel.lat,
lon: vessel.lon,
datetime: vessel.received_time,
heading: vessel.hdg,
sog: vessel.sog,
shiptype_descr: vessel.shiptype_descr,
last_positional_update: vessel.last_updated
};
marker.bindPopup(popupNeutralMarker, {
maxWidth: 392,
className: `map-info`
});
neutralMarkers.push(marker);
if (neutralMarkers.length >= numOfVessels) {
ciLayer.addLayers(neutralMarkers);
const vesselsInROI = document.getElementById('vessels-in-roi');
vesselsInROI.innerHTML = numOfVessels;
}
}
function checkROIBoundaries(latitude, longitude) {
let canInclude = false;
const lLatOK =
latitude >= Math.min(nwLat, seLat) &&
latitude <= Math.max(nwLat, seLat);
const lLonOK =
longitude >= Math.min(nwLon, seLon) &&
longitude <= Math.max(nwLon, seLon);
if (lLatOK && lLonOK) canInclude = true;
else numOfVessels--;
return canInclude;
}
function SetROI(pROI) {
return new Promise((resolve, reject) => {
try {
if (pROI.nwlat + pROI.nwlon + pROI.selat + pROI.selon === 0) return;
const defaultBoundaryStyle = {
color: 'blue',
fillColor: 'lightblue',
fillOpacity: 0.2
}
ROI = new L.rectangle(
[
[pROI.selat, pROI.selon],
[pROI.nwlat, pROI.selon],
[pROI.selat, pROI.selon],
[pROI.selat, pROI.nwlon]
],
defaultBoundaryStyle
)
sMap.addLayer(ROI, true);
// Center ROI
sMap.fitBounds([
[gOrganizationPrefs.roinwse.nwlat, gOrganizationPrefs.roinwse.nwlon],
[gOrganizationPrefs.roinwse.selat, gOrganizationPrefs.roinwse.selon]
]);
resolve('OK');
}
catch (err) {
console.log("error is: ", err, "\n");
reject({ error: err, function: 'SetROI'});
}
})
}
using the stickman example of http://fabricjs.com/,
I have been trying to achieve moving the related circles when a line is moved. The code in the example is not well structured, heavy & with errors :), as I can not to move the the related circles symmetrically.
If in the //move the other circle part is used next line
obj.set({
'left': (s.calcLinePoints().x1 + _l),
'top': (-s.calcLinePoints().y1 + _t)
});
the difference is in the sign of collected information for y1 and we move some horizontal line visually the result OK, but in my opinion this type of "adjustment" is not the correct one...
[example code]
$(function() {
//create the fabriccanvas object & disable the canvas selection
var canvas = new fabric.Canvas('c', {
selection: false
});
//move the objects origin of transformation to the center
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
function makeCircle(left, top, line1, line2, usedLine, usedEnd) {
//used line - used line for the center
//usedEnd - fromt the used line
var c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 2,
radius: 6,
fill: '#fff',
stroke: '#666'
});
c.hasControls = c.hasBorders = false;
c.line1 = line1;
c.line2 = line2;
//add information which line end is used for center
var _usedLineName;
if (usedLine == 1) {
_usedLineName = line1.name;
} else {
_usedLineName = line2.name;
}
c.usedLineName = _usedLineName;
c.usedEndPoint = usedEnd;
return c;
}
function makeLine(coords, name) {
var l = new fabric.Line(coords, {
stroke: 'red',
strokeWidth: 4,
selectable: true, //false
name: name
});
l.hasControls = l.hasBorders = false;
return l;
}
//initial shape information
var line = makeLine([250, 125, 350, 125], "l1"),
line2 = makeLine([350, 125, 350, 225], "l2"),
line3 = makeLine([350, 225, 250, 225], "l3"),
line4 = makeLine([250, 225, 250, 125], "l4");
canvas.add(line, line2, line3, line4);
canvas.add(
makeCircle(line.get('x1'), line.get('y1'), line4, line, 1, 2),
makeCircle(line.get('x2'), line.get('y2'), line, line2, 1, 2),
makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, 1, 2),
makeCircle(line3.get('x2'), line3.get('y2'), line3, line4, 1, 2));
canvas.on('object:moving', function(e) {
//find the moving object type
var objType = e.target.get('type');
var p = e.target;
if (objType == 'circle') {
p.line1 && p.line1.set({
'x2': p.left,
'y2': p.top
});
p.line2 && p.line2.set({
'x1': p.left,
'y1': p.top
});
//set coordinates for the lines - should be done if element is moved programmely
p.line2.setCoords();
p.line1.setCoords();
canvas.renderAll();
} else if (objType == 'line') {
//loop all circles and if some is with coordinates as some of the ends - to change them
for (var i = 0; i < canvas.getObjects('circle').length; i++) {
var currentObj = canvas.getObjects('circle')[i];
if (currentObj.get("usedLineName") == e.target.get('name')) {
//usedEndPoint=2
for (var ss = 0; ss < canvas.getObjects('line').length; ss++) {
var s = canvas.getObjects('line')[ss];
//console.log(s.calcLinePoints())
//console.log(s.calcLinePoints().y2)
var _l = s.left;
var _t = s.top;
if (s.get("name") == currentObj.get("usedLineName")) {
currentObj.set({
'left': (s.calcLinePoints().x2 + _l),
'top': (s.calcLinePoints().y2 + _t)
});
console.log(s.calcLinePoints().y2 + _t)
currentObj.setCoords();
currentObj.line1 && currentObj.line1.set({
'x2': currentObj.left,
'y2': currentObj.top
});
currentObj.line2 && currentObj.line2.set({
'x1': currentObj.left,
'y1': currentObj.top
});
currentObj.line2.setCoords();
currentObj.line1.setCoords();
//move the other circle
canvas.forEachObject(function(obj) {
var _objType = obj.get('type');
if (_objType == "circle" && obj.line2.name == s.get("name")) {
obj.set({
'left': (s.calcLinePoints().x1 + _l),
'top': (s.calcLinePoints().y1 + _t)
});
console.log(s.calcLinePoints().y1 + _t)
obj.setCoords();
obj.line1 && obj.line1.set({
'x2': obj.left,
'y2': obj.top
});
obj.line2 && obj.line2.set({
'x1': obj.left,
'y1': obj.top
});
obj.line2.setCoords();
obj.line1.setCoords();
//canvas.renderAll();
}
});
canvas.renderAll();
//end move oter
}
}
}
}
}
});
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
Here it is the code on jsfiddle, too:
https://jsfiddle.net/muybien/mzsa3z9L/
I want previously to thank you, even only for reading the question.
Thanks of MiltoxBeyond's suggestion, the problem is fixed.
Here it is a working and little cleaned example:
//to save the old cursor position: used on line mooving
var _curX, _curY;
$(function() {
//create the fabriccanvas object & disable the canvas selection
var canvas = new fabric.Canvas('c', {
selection: false
});
//move the objects origin of transformation to the center
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
function makeCircle(left, top, line1, line2) {
var c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 2,
radius: 6,
fill: '#fff',
stroke: '#666'
});
c.hasControls = c.hasBorders = false;
c.line1 = line1;
c.line2 = line2;
return c;
}
function makeLine(coords, name) {
var l = new fabric.Line(coords, {
stroke: 'red',
strokeWidth: 4,
selectable: true, //false
name: name
});
l.hasControls = l.hasBorders = false;
return l;
}
//initial shape information
var line = makeLine([250, 125, 350, 125], "l1"),
line2 = makeLine([350, 125, 350, 225], "l2"),
line3 = makeLine([350, 225, 250, 225], "l3"),
line4 = makeLine([250, 225, 250, 125], "l4");
canvas.add(line, line2, line3, line4);
canvas.add(
makeCircle(line.get('x1'), line.get('y1'), line4, line), makeCircle(line.get('x2'), line.get('y2'), line, line2), makeCircle(line2.get('x2'), line2.get('y2'), line2, line3), makeCircle(line3.get('x2'), line3.get('y2'), line3, line4)
);
canvas.on('object:selected', function(e) {
//find the selected object type
var objType = e.target.get('type');
if (objType == 'line') {
_curX = e.e.clientX;
_curY = e.e.clientY;
//console.log(_curX);
//console.log(_curY);
}
});
canvas.on('object:moving', function(e) {
//find the moving object type
var p = e.target;
var objType = p.get('type');
if (objType == 'circle') {
p.line1 && p.line1.set({
'x2': p.left,
'y2': p.top
});
p.line2 && p.line2.set({
'x1': p.left,
'y1': p.top
});
//set coordinates for the lines - should be done if element is moved programmely
p.line2.setCoords();
p.line1.setCoords();
canvas.renderAll();
} else if (objType == 'line') {
var _curXm = (_curX - e.e.clientX);
var _curYm = (_curY - e.e.clientY);
//console.log("moved: " + _curXm);
//console.log("moved: " + _curYm);
//loop all circles and if some contains the line - move it
for (var i = 0; i < canvas.getObjects('circle').length; i++) {
var currentObj = canvas.getObjects('circle')[i];
if (currentObj.line1.get("name") == p.get('name') || currentObj.line2.get("name") == p.get('name')) {
currentObj.set({
'left': (currentObj.left - _curXm),
'top': (currentObj.top - _curYm)
});
currentObj.setCoords();
currentObj.line1 && currentObj.line1.set({
'x2': currentObj.left,
'y2': currentObj.top
});
currentObj.line2 && currentObj.line2.set({
'x1': currentObj.left,
'y1': currentObj.top
});
currentObj.line2.setCoords();
currentObj.line1.setCoords();
}
}
_curX = e.e.clientX;
_curY = e.e.clientY;
}
});
});
canvas {
border: 1px solid #808080;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
I use Ajax to get data, when I debug with firebug, the result shows highcharts option's data has data. But the chart can't render correctly. The charts background is rended correctely, but there is no chart.
here is my code.
// # author:wang
var chart;
var element;
var chart_type_element;
var y_title_1;
var y_title_2;
var y_title_3;
var date = new Date();
var y = date.getUTCFullYear();
var m = date.getUTCMonth();
var d = date.getUTCDate()-1;
var h = date.getUTCHours();
var minute = date.getUTCMinutes();
/**
* 返回图表的类型
*
*/
function chart_type(element){
var type;
var wind = '风向风速';
var t_h = '温湿度';
if ( element== 'wind' ){
type = wind;
} else if ( element == 't_h') {
type = t_h;
}
return type;
}
/**
*
*return y-axis title
*
*/
function y_title(element, serie){
var title;
if ( element== 'wind' ){
switch (serie){
case 1: title = '风速'; break;
case 2: title = '阵风'; break;
case 3: title = '风向'; break;
}
} else if ( element == 't_h') {
switch (serie){
case 1: title = '温度'; break;
case 2: title = '湿度'; break;
default: title = '';
}
}
return title;
}
function getLocTime(nS) {
return new Date(parseInt(nS)).toLocaleString().replace(/年|月/g, "-").replace(/日/g, " ");
}
/**
* 气压配置选项
*/
var option_p = {
chart: {
renderTo: 'station_curve',
zoomType: 'x'
},
title:{
text:'气压序列图'
},
subtitle: {
text: '信科气象台'
},
xAxis: {
type: 'datetime',
maxZoom: 3600000, // one hour
title: {
text: null
}
},
yAxis: {
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
min:980,
max:1040
},
tooltip: {
formatter: function() {
return getLocTime(this.x) +': '+ this.y;
}
},
legend: {
layout: 'vertical',
align: 'left',
x: 220,
verticalAlign: 'top',
y: 30,
floating: true,
backgroundColor: '#FFFFFF'
},
series: [{
name: '海平面气压',
color: '#4572A7',
type: 'line',
pointInterval: 60 * 1000,
pointStart: Date.UTC(y,m,d,h,minute),
marker: {
enabled: false
}
}, {
name: '甲板气压',
type: 'line',
color: '#AA4643',
pointInterval: 60 * 1000,
pointStart: Date.UTC(y,m,d,h,minute),
marker: {
enabled: false
}
}/*, {
name: '3',
color: '#89A54E',
pointInterval: 60 * 1000,
pointStart: Date.UTC(y,m,d,h,minute),
type: 'spline',
marker: {
enabled: false
}
}*/]
};
function draw_curve(platformID,element){
option.series[0].data = [];
option.series[1].data = [];
option_th.series[0].data = [];
option_th.series[1].data = [];
jQuery.getJSON('get_last_3d.php',{platformID:platformID,element:element}, function(data) {
var serie=[];
var serie1=[];
if (element == 'wind_dir'){
$.each(data,function(i,value){
serie[i]=parseInt(value.wd);
});
option.series[0].data = serie.reverse();
} else if (element == 'wind_speed'){
$.each(data,function(i,value){
serie[i]=parseInt(value.ws);
serie1[i]=parseInt(value.ws_max);
});
option_wind_speed.series[0].data = serie.reverse();
option_wind_speed.series[1].data = serie1.reverse();
} else if (element == 't_h') {
$.each(data,function(i,value){
serie[i]=parseInt(value.t);
serie1[i]=parseInt(value.h);
});
option_th.series[0].data = serie.reverse();
option_th.series[1].data = serie1.reverse();
} else if (element == 'p') {
$.each(data,function(i,value){
serie[i]=parseInt(value.sea_p);
serie1[i]=parseInt(value.deck_p);
});
option_p.series[0] = serie.reverse();
option_p.series[1] = serie1.reverse();
} else if (element == 'wave_height') {
$.each(data,function(i,value){
serie[i]=parseInt(value.wave_height);
});
option.series[0].data = serie.reverse();
} else if (element == 'visibility') {
$.each(data,function(i,value){
serie[i]=parseInt(value.visibility);
});
option.series[0].data = serie.reverse();
} else if (element == 'cloudheight') {
$.each(data,function(i,value){
serie[i]=parseInt(value.cloud_height);
});
option.series[0].data = serie.reverse();
}
switch(element){
case 'p' :
chart = new Highcharts.Chart(option_p);
break;
case 't_h':
chart = new Highcharts.Chart(option_th);
break;
case 'wind_speed':
chart = new Highcharts.Chart(option_wind_speed);
break;
default:
chart = new Highcharts.Chart(option);
}
/* old code, will be replaced with switch
if (element == 'p')
chart = new Highcharts.Chart(option_p);
else {
chart = new Highcharts.Chart(option);
}
*/
});
}
$( function(){
draw_curve(105,'t_h');
})//end of jquery function
![the chart][1]
thank you advance
The reason it doesn't work is because you didn't provide the values for y,m,d,h,minute for the Date.UTC(y,m,d,h,minute) in the pointStart property for your series. See working: http://jsfiddle.net/LzfM3/