Raycaster display a Render - reactjs

I use Threejs and I would like to create a function to display a descriptive card (Render() of Satllite.js) when I click on a Sphere. (Satellite.js)
/********** Imports **********/
import React, { PureComponent } from 'react';
import * as THREE from 'three';
import satData from '../data/sat.json';
export class Satellites extends PureComponent {
constructor(props) {
super(props)
this.state = { open: true }
this.x = {};
this.mouse = {};
this.raycaster = new THREE.Raycaster();
this.mouse = new THREE.Vector2();
}
onDocumentMouseDown = event => {
event.preventDefault()
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
// find intersections
this.raycaster.setFromCamera(this.mouse, this.props.camera)
this.intersects = this.raycaster.intersectObjects(
this.scene.className("card"),
false
)
if (this.intersects.length > 0) {
if (this.intersects[0].object.callback)
this.intersects[0].object.callback()
this.intersects[0].className(".card")
this.particle = new THREE.Sprite(this.particleMaterial)
this.particle.position.copy(this.intersects[0].point)
this.particle.scale.x = this.particle.scale.y = 16
this.props.scene.add(this.particle)
}
}
componentDidMount() {
// Satellite Sphere
// this.geometry = new THREE.SphereGeometry( this.props.data.r, 32, 32 );
this.geometry = new THREE.SphereGeometry(10, 32, 32)
this.material = new THREE.MeshBasicMaterial({ color: 0xffff00 })
this.sphere = new THREE.Mesh(this.geometry, this.material)
this.sphere.callback = function() {
console.log('Toto!')
}
this.sphere.position.set(50, 50, 50)
this.props.scene.add(this.sphere)
document.addEventListener('mousedown', this.onDocumentMouseDown, true)
}
// componentDidUpdate() {
// // update satelite pos.
// const radius = 10;
// const scale = radius * 1;
// this.sphere.scale.x = scale;
// this.sphere.scale.y = scale;
// this.sphere.scale.z = scale;
// }
componentWillUnmount() {
document.removeEventListener('mousedown', this.onDocumentMouseDown);
}
render() {
return (
<div>
{satData.map((satDetail, index) => {
return <div key={index} className="card">
<h2>{satDetail.satName.toUpperCase()}</h2>
<div className="cardImg" >
<img src={satDetail.satImg} alt={satDetail.satAlt} />
</div>
<div>
<p>Altitude : <span>{satDetail.alt}</span> km</p>
<p>Longitude : <span>{satDetail.long}</span> °</p>
<p>Latitude : <span>{satDetail.lat}</span> °</p>
</div>
<button onClick={this.closeModal}>Fermer</button>
</div>
})}
</div>
)
}
}
More details here
I got the code of a tutorial that show white squares but I would like to display my div ".card" which is in the "Render"
What is the method ?
Thanks for help !

This answer involves many topics combined, basically you need:
Raycast the mouse click and find the object intersection,
Get info by picked object,
Display it if object was selected, or hide if nothing was picked by mouse.
Test it here: http://jsfiddle.net/mmalex/9k4qbL8s/
let cardShown = false;
function showCard(userText) {
var divElement = $("#card");
if (divElement) {
if (!cardShown) {
divElement.css({
display: "block",
opacity: 0,
height: "0px"
});
}
divElement.text("Object color: " + userText);
if (!cardShown) {
setTimeout(function() {
divElement.css({
opacity: 1,
height: "16px"
});
}, 25);
}
cardShown = true;
}
}
function hideCard() {
var divElement = $("#card");
if (divElement) {
divElement.css({
height: "0px",
opacity: 0
});
cardShown = false;
}
}
var scene = new THREE.Scene();
var raycaster = new THREE.Raycaster();
//create some camera
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 5;
camera.position.y = 5;
camera.position.z = 5;
camera.lookAt(0, 0, 0);
var controls = new THREE.OrbitControls(camera);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color(0x595959));
document.body.appendChild(renderer.domElement);
// white spotlight shining from the side, casting a shadow
var spotLight = new THREE.SpotLight(0xffffff, 2.5, 25, Math.PI / 6);
spotLight.position.set(4, 10, 7);
scene.add(spotLight);
// collect objects for raycasting,
// for better performance don't raytrace all scene
var clickableObjects = [];
var colors = new RayysWebColors();
for (let k = 0; k < 12; k++) {
var size = 0.5;
var geometry = new THREE.BoxGeometry(size, 0.2, size);
var randomColor = colors.pickRandom();
var material = new THREE.MeshPhongMaterial({
color: randomColor.hex,
transparent: true,
opacity: 0.75
});
var cube = new THREE.Mesh(geometry, material);
cube.userData.userText = randomColor.name;
cube.applyMatrix(new THREE.Matrix4().makeTranslation(k % 3, 0, Math.floor(k / 3) - 1));
scene.add(cube);
clickableObjects.push(cube);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
// this will be 2D coordinates of the current mouse position, [0,0] is middle of the screen.
var mouse = new THREE.Vector2();
var clickedObj; // this objects is hovered at the moment
// Following two functions will convert mouse coordinates
// from screen to three.js system (where [0,0] is in the middle of the screen)
function updateMouseCoords(event, coordsObj) {
coordsObj.x = ((event.clientX - renderer.domElement.offsetLeft + 0.5) / window.innerWidth) * 2 - 1;
coordsObj.y = -((event.clientY - renderer.domElement.offsetTop + 0.5) / window.innerHeight) * 2 + 1;
}
function onMouseUp(event) {
updateMouseCoords(event, mouse);
latestMouseProjection = undefined;
clickedObj = undefined;
raycaster.setFromCamera(mouse, camera); {
var intersects = raycaster.intersectObjects(clickableObjects);
if (intersects.length > 0) {
latestMouseProjection = intersects[0].point;
clickedObj = intersects[0].object;
showCard(clickedObj.userData.userText);
} else {
clickedObj = undefined;
hideCard();
}
}
}
window.addEventListener('mouseup', onMouseUp, false);
animate();

Related

The app gets slower with every change in props [duplicate]

This question already has an answer here:
React won't draw anything in the canvas in useEffect
(1 answer)
Closed 16 days ago.
I use Matter js for physics and canvas for rendering 100 items, after every change in props the app gets slower and slower. At the same time, subsequent downloads with the same props occur instantly, i.e. past images and elements remained and were not deleted, which loads the application.
enter image description here
"Top" dropdown menu changes props for bubbles component, code:
const Bubbles = ({ coins }) => {
var winwidth = window.innerWidth;
var winheight = window.innerHeight - 80;
const [physics, setPhysics] = useState({
frictionAir: 0,
friction: 0.2,
frictionStatic: 0.2,
restitution: 0.1,
inertia: Infinity,
density: 0.8,
});
useEffect(() => {
setSize(coins);
// create an engine
const engine = Engine.create();
const world = engine.world;
// create a renderer
const render = Render.create({
element: document.querySelector(".bubbles"),
engine: engine,
options: {
width: winwidth,
height: winheight,
showAngleIndicator: false,
background: "transparent",
wireframeBackground: "transparent",
wireframes: false,
showDebug: false,
},
});
const bubbles = [];
// create a canvas
const canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.querySelector(".bubbles").appendChild(canvas);
const ctx = canvas.getContext("2d");
// create 100 random bubbles
for (let i = 0; i < coins.length; i++) {
const x = Math.random() * window.innerWidth;
const y = Math.random() * window.innerHeight;
const bubble = Bodies.circle(x, y, coins[i].size / 2, {
...physics,
render: {
fillStyle: "transparent",
},
});
Composite.add(engine.world, bubble);
// store the bubble and its content data in an object
bubbles.push({
bubble,
content: {
radius: coins[i].radius,
text: `${i + 1}`,
},
});
}
// update the canvas on each engine update
Matter.Events.on(engine, "afterUpdate", function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < bubbles.length; i++) {
const bubble = coins[i];
const pos = bubbles[i].bubble.position;
const size = bubble.size;
const text = bubble.symbol;
const priceChange = bubble.price_change_percentage_24h.toFixed(1);
const image = new Image();
image.src = bubble.image;
if (priceChange > 0) {
ctx.fillStyle = "rgba(5, 222, 5, 0.15)";
ctx.strokeStyle = "rgba(5, 222, 5, 0.6)";
} else if (priceChange < 0) {
ctx.fillStyle = "rgba(166, 53, 53, 0.15)";
ctx.strokeStyle = "rgba(166, 53, 53, 0.8)";
} else {
ctx.fillStyle = "rgba(255, 255, 89, 0.069)";
ctx.strokeStyle = "rgba(187, 231, 11, 0.443)";
}
ctx.beginPath();
ctx.arc(pos.x, pos.y, size / 2, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.drawImage(
image,
pos.x - size / 5,
pos.y - size / 2.5,
size / 2.5,
size / 2.5
);
ctx.font = `${size / 6}px Acme`;
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, pos.x, pos.y + size / 6.5);
ctx.font = `${size / 6.5}px Acme`;
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(priceChange + "%", pos.x, pos.y + size / 3);
}
});
// fit the render viewport to the scene
window.addEventListener("onload", () => {
Render.lookAt(render, {
min: { x: 0, y: 0 },
max: { x: 100000, y: 10000 },
});
});
// run the engine
Runner.run(engine);
// run the renderer
Render.run(render);
return () => {
// stop the engine and renderer
Engine.clear(engine);
Render.stop(render);
Runner.stop(engine);
// remove the canvas from the DOM
canvas.remove();
};
}, [coins]);
return <></>;
};
export default Bubbles;
after each update of the coins props, I deleted the canvas and stopped the engine, but still the speed worsened
return () => {
// stop the engine and renderer
Engine.clear(engine);
Render.stop(render);
Runner.stop(engine);
// remove the canvas from the DOM
canvas.remove();
};
I want to either stop re-creating the engine and the matter js world, canvas with images.
Only without window.location.reload(), because I need to save props like "Top" and "Earth, Trampoline", etc.
I solved the problem. I didn't properly clear the js canvas value and also didn't set events.off when unmounting the component.
Here is the solution to my problem
return () => {
//set Matter Js events off. drawCanvas - afterUpdate event function
Events.off(engine, 'afterUpdate', drawCanvas);
Render.stop(render);
Composite.clear(engine.world);
Runner.stop(engine)
Engine.clear(engine);
render.canvas.remove();
render.canvas = null;
render.context = null;
// remove the canvas from the DOM
canvas.remove();
};

How do I get the camera to focus on the object and keep it in center focus using Babylonjs?

What I really want is to put the mesh on the object and have the camera focus on that mesh. I think they do this with the lookAt function, but I don't know how to use it correctly.
I got help from this page : https://www.babylonjs-playground.com/#1CSVHO#12
I tried some function demos.
setCamera_Mesh = () => {
let { currentWidth, currentDepth, rowCount } = this.currentConfig;
let sphere = Mesh.CreateSphere("sphere", 1, this.scene);
let referenceBox = Mesh.CreateBox("referenceBox", { width: 1, height: 1, depth: 1, updatable: true });
sphere.scaling = new Vector3(0.1, 0.1, 0.1);
sphere.position = this.scene.cameras[0].position;
sphere.parent = this.scene.cameras[0];
this.referenceBox && this.referenceBox.dispose()
referenceBox.position = new Vector3(0, 0, 0.08);
referenceBox.enableEdgesRendering();
referenceBox.edgesWidth = 1;
referenceBox.edgesColor = new Color4(0, 0, 1, 0.05);
referenceBox.visibility = 0.5;
referenceBox.scaling = new Vector3(currentDepth / 40, rowCount / 3, currentWidth / 100);
this.referenceBox = referenceBox;
sphere.lookAt(referenceBox.position);
}
I had to use setParent () instead of .parent where I added the camera as parent.
When I edit the code as below, it worked correctly.
setCameraToMesh = () => {
let { currentWidth, currentDepth, rowCount } = this.currentConfig;
let sphere = MeshBuilder.CreateSphere("referenceSphere", this.scene);
let referenceBox = MeshBuilder.CreateBox("referenceBox", { width: 0.1, height: 0.1, depth: 0.1, updatable: true });
sphere.scaling = new Vector3(0.1, 0.1, 0.1);
sphere.position = this.scene.cameras[0].position;
sphere.setParent(this.scene.cameras[0]);
this.referenceBox && this.referenceBox.dispose()
referenceBox.position = new Vector3(0, rowCount / 500, 0.08);
referenceBox.enableEdgesRendering();
referenceBox.edgesWidth = 1;
referenceBox.edgesColor = new Color4(0, 0, 1, 0.05);
referenceBox.visibility = 0.05;
referenceBox.scaling = new Vector3(currentDepth / 40, rowCount / 3, currentWidth / 100);
this.referenceBox = referenceBox;
sphere.lookAt(referenceBox.absolutePosition);
this.scene.cameras[0].focusOn([referenceBox], true);
}

Load from JSON with dynamic patterns, patternSourceCanvas is not defined error return by the serialize JSON data

I am trying to save Fabric.js canvas and reload it using loadFromJson. But I am getting error patternSourceCanvas is not defined. I thought I should make it global so I removed var.
How to set the global variable in Fabric JS and use var patternSourceCanvas?
When I use the code below, then everything is working fine and the JSON is loaded easily.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.util.loadImage(t, function(t) {
var svg_width = i.width;
console.log('svg widh' + i.width + 'svg height' + i.height);
console.log('img width t'+ t.width + ' img height' + t.height);
if(svg_width >= 300){
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill({
source: t, repeat: 'repeat', offsetX:200 , offsetY : -110 // working
}), e.fabric.renderAll();
console.log('in if image 300 up ', t);
} else if (i.paths){
for (var r = 0; r < i.paths.length; r++)
i.paths[r].setPatternFill({
source: t, repeat: 'repeat' , offsetX: -100 , offsetY:-110
}), e.fabric.renderAll();
console.log('in image elseeee 300 up ', t);
}
}
})
But when I fill some other new shape with the new patternSourceCanvas variable then it's not working. Kindly help me with dynamic patterns.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.Image.fromURL(t, function (img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: img.getScaledWidth() ,
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
return patternSourceCanvas.getElement();
},
repeat: r
});
console.log('pattern', pattern);
//p.set('fill', pattern);
canvas.renderAll();
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill(pattern);
} else if(i.paths) {
for (var r = 0; r < i.paths.length; r++) {
i.paths[r].setPatternFill(pattern);
}
}
e.fabric.renderAll();
});
You need to put patternSourceCanvas to global scope/ scope where loadFromJSON can access patternSourceCanvas. Else you can use cors enabled image directly.
DEMO
var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/22/Wikimapia_logotype.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
width: 200,
height: 200,
strokeWidth: 2,
stroke: '#000'
})
canvas.add(rect);
fabric.Image.fromURL(imageUrl, function(img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.setDimensions({
width: img.getScaledWidth(),
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: patternSourceCanvas.getElement()
},
function(patternObj) {
rect.fill = patternObj;
rect.dirty = true;
canvas.renderAll();
});
}, {
crossOrigin: 'annonymous'
});
function loadfromjson() {
var json = canvas.toJSON();
canvas.clear();
setTimeout(function() {
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
}, 1000)
}
canvas{
border:2px solid #000;
}
<canvas id="canvas" width="300" height="300"></canvas><br>
<button onclick="loadfromjson()">loadfromjson </button>
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>

No tooltips lines displayed in line chart - dc.js,d3 v4.2.8,React

Interested in rendering vertical and horizontal tooltip lines in a line chart. Using dc.js, d3.js ver 4.2.8,React. In the original version it works well
Tootltip lines are being displayed
,but not in the React version:
Tooltip lines are not being displayed
.The code:
//////Line.js
import React, { PropTypes } from 'react';
import ReactDOM from "react-dom";
import * as d3 from 'd3';
import dc from "dc";
import * as crossfilter from 'crossfilter';
import {Jumbotron } from 'react-bootstrap';
import functionDCHelper from './functionDCHelper';
import {scaleTime, scaleLinear} from 'd3-scale';
import { axisLeft, axisBottom } from 'd3-axis';
import TableChart from "../components/TableChart.js";
class LineChart extends React.Component {
componentDidMount() {
var bitrateLineChart = dc.compositeChart(this.refs.lineChart);
var { min15, minDate, maxDate, bitrateWeekMinIntervalGroupMove, maxbit } = functionDCHelper.generateValues(this.props.data);
bitrateLineChart
.xUnits(min15.range)
.x(d3.scaleTime().domain([new Date(minDate), new Date(maxDate)]))
.yAxisPadding('5%')
.elasticY(true)
.width(990)
.height(200)
.transitionDuration(500)
.margins({ top: 30, right: 50, bottom: 25, left: 50, padding: 1 })
.mouseZoomable(true)
.brushOn(false)
.renderHorizontalGridLines(true)
.legend(dc.legend().x(800).y(10).itemHeight(13).gap(5))
//Render max bitrate horizontal line copied from bar-extra-line.html
.yAxisLabel("Total Bitrate per 15 minutes")
.on('renderlet', function (chart) {
chart.svg().selectAll('.chart-body').attr('clip-path', null)
var left_y = 10, right_y = 70; // use real statistics here!
var extra_data = [{ x: chart.x().range()[0], y: chart.y()(left_y) }, { x: chart.x().range()[1], y: chart.y()(right_y) }];
var line = d3.line()
.x(function (d) { return d.x; })
.y(function (d) { return maxbit; })
.curve(d3.curveLinear); //.interpolate('linear');
var chartBody = chart.select('g.chart-body');
var path = chartBody.selectAll('path.extra').data([extra_data]);
path.enter().append('path').attr({
class: 'extra',
stroke: 'red',
id: 'extra-line',
});
path.attr('d', line);
// Label the max line
var text = chartBody.selectAll('text.extra-label').data([0]);
text.enter().append('text')
.attr('text-anchor', 'middle')
.append('textPath').attr({
class: 'extra-label',
'xlink:href': '#extra-line',
startOffset: '50%'
})
.text('Total Bitrate Max Value');
})
// Title can be called by any stack layer.
.title(function (d) {
var value = d.value.total ? d.value.total : d.value;
if (isNaN(value)) {
value = 0;
}
return functionDCHelper.dateFormat(d.key) + ' \n Total Bit:' + functionDCHelper.numberFormat(value)
})
//Creating dynamic Y axis with min max ticks' values depending on min max of data - copied from http://jsfiddle.net/gordonwoodhull/7anae5c5/1/
.compose([
functionDCHelper.nonzero_min(dc.lineChart(bitrateLineChart)
.dimension(min15)
.colors('green')
.group(bitrateWeekMinIntervalGroupMove, 'Bitrate Total')
.valueAccessor(function (d) {
return d.value.total;
})
// .dashStyle([2,2])
.interpolate('d3.curveStepAfter')
.renderArea(false)
.brushOn(false)
.renderDataPoints(false)
.clipPadding(10)),
])
bitrateLineChart.render();
}
render() {
return(
<div ref="lineChart">
</div>
);
}
}
export default LineChart;
//////functionDCHelper.js
import crossfilter from 'crossfilter';
import * as d3 from 'd3';
import dc from 'dc';
var minDate,min15,bitrateWeekMinIntervalGroupMove,maxDate,minIntervalWeekBitrateGroup,dateDimension,dateFormat,numberFormat,maxbit;
function nonzero_min(chart) {
dc.override(chart, 'yAxisMin', function () {
var min = d3.min(chart.data(), function (layer) {
return d3.min(layer.values, function (p) {
return p.y + p.y0;
});
});
return dc.utils.subtract(min, chart.yAxisPadding());
});
return chart;
}
// 15 Min Interval - copied from https://github.com/mbostock/d3/blob/master/src/time/interval.js
var d3_date = Date;
function d3_time_interval(local, step, number) {
function round(date) {
var d0 = local(date), d1 = offset(d0, 1);
return date - d0 < d1 - date ? d0 : d1;
}
function ceil(date) {
step(date = local(new d3_date(date - 1)), 1);
return date;
}
function offset(date, k) {
step(date = new d3_date(+date), k);
return date;
}
function range(t0, t1, dt) {
var time = ceil(t0), times = [];
if (dt > 1) {
while (time < t1) {
if (!(number(time) % dt)) times.push(new Date(+time));
step(time, 1);
}
} else {
while (time < t1) times.push(new Date(+time)), step(time, 1);
}
return times;
}
function range_utc(t0, t1, dt) {
try {
d3_date = d3_date_utc;
var utc = new d3_date_utc();
utc._ = t0;
return range(utc, t1, dt);
} finally {
d3_date = Date;
}
}
local.floor = local;
local.round = round;
local.ceil = ceil;
local.offset = offset;
local.range = range;
var utc = local.utc = d3_time_interval_utc(local);
utc.floor = utc;
utc.round = d3_time_interval_utc(round);
utc.ceil = d3_time_interval_utc(ceil);
utc.offset = d3_time_interval_utc(offset);
utc.range = range_utc;
return local;
}
function d3_time_interval_utc(method) {
return function (date, k) {
try {
d3_date = d3_date_utc;
var utc = new d3_date_utc();
utc._ = date;
return method(utc, k)._;
} finally {
d3_date = Date;
}
};
}
// generalization of d3.time.minute copied from- https://github.com/mbostock/d3/blob/master/src/time/minute.js
function n_minutes_interval(nmins) {
var denom = 6e4 * nmins;
return d3_time_interval(function (date) {
return new d3_date(Math.floor(date / denom) * denom);
}, function (date, offset) {
date.setTime(date.getTime() + Math.floor(offset) * denom); // DST breaks setMinutes
}, function (date) {
return date.getMinutes();
});
}
min15 = n_minutes_interval(15);
dateFormat = d3.timeFormat('%Y/%m/%d/%H:%M');
numberFormat = d3.format('d');
//### Crossfilter Dimensions
function generateValues(data) {
data.forEach(function (d) {
d.bitdate = new Date(d.DATETIME); //d.DATETIME = dateFormat.parse(d.DATETIME);
// d.month = d3.time.month(d.bitdate);
// d.week = d3.time.week(d.bitdate);
d.BITRATE = +d.BITRATE.match(/\d+/); //d.BITRATE = +d.BITRATE;
});
var crossFilteredData = crossfilter(data);
var all = crossFilteredData.groupAll();
// Dimension by full date
dateDimension = crossFilteredData.dimension(function (d) {
return d.bitdate;
});
maxbit = d3.max(data, function (d) { return +d["BITRATE"]; }); //alert(maxbit);
//Group bitrate per week, 15 minInterval - maintain running tallies
bitrateWeekMinIntervalGroupMove = dateDimension.group(min15).reduce(
/* callback for when data is added to the current filter results */
function (p, v) {
++p.count;
p.BITRATE = +v.BITRATE;
p.total += +v.BITRATE;
p.avg = p.count ? Math.round(p.total / p.count) : 0;
return p;
},
/* callback for when data is removed from the current filter results */
function (p, v) {
--p.count;
p.BITRATE = +v.BITRATE;
p.total -= +v.BITRATE;
p.avg = p.count ? Math.round(p.total / p.count) : 0;
return p;
},
/* initialize p */
function () {
return {
count: 0,
bitrate: 0,
total: 0,
avg: 0
};
}
);
try {
minDate = dateDimension.bottom(1)[0].DATETIME;
} catch(err) {
minDate = new Date("2016-06-14 0:00");
}
try {
maxDate = dateDimension.top(1)[0].DATETIME;
} catch(err) {
maxDate = new Date("2016-06-18 23:55");
}
return {
min15, minDate, maxDate, bitrateWeekMinIntervalGroupMove,minIntervalWeekBitrateGroup,dateDimension,maxbit
};
}
export default {
generateValues,
nonzero_min,
dateFormat,
numberFormat
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
path.line {
fill: none;
stroke: green;
stroke-width: 1.5px;
}
.y.axis line,
.y.axis path {
fill: none;
stroke: black;
}
.x.axis line,
.x.axis path {
fill: none;
stroke: black;
}
</style>
<title>Line Chart DC.js,React</title>
</head>
<body>
<div id="App"></div>
<script src="/bundle.js"></script>
</body>
</html>
Any help would be appreciated
The current solution is to place inside the index.html the following styling:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
path.yRef{
storke-width:2;
stroke:red;
dislplay:inline;
}
path.xRef{
storke-width:2;
stroke:red;
dislplay:inline;
}
</style>
<title>Line Chart DC.js,React</title>
</head>
<body>
<div id="App"></div>
<script src="/bundle.js"></script>
</body>
</html>
Would prefer to handle it inside the chart's js (Line.js) or in the css class,any suggestions would be welcomed. The display:
Dc.js, tooltip lines displayed

getting Cannot read property '0' of undefined when i click google map marker?

I am getting error when i click google map marker how to solve this problem i have enclosed fiddle http://jsfiddle.net/cLADs/135/ .when i click button it should pass id value based on marker click some one help me out to move forward.
var gmarkers1 = [];
var markers1 = [];
var infowindow = new google.maps.InfoWindow({
content: ''
});
// Our markers
markers1 = [
['0', 'Madivala', 12.914494, 77.560381, 'car','as12'],
['1', 'Majestic', 12.961229, 77.559281, 'third','as13'],
['2', 'Ecity', 12.92489905, 77.56070772, 'car','as14'],
['3', 'Jp nagar', 12.91660662, 77.52047465, 'second','as15']
];
/**
* Function to init map
*/
function initialize() {
var center = new google.maps.LatLng(12.9667,77.5667);
var mapOptions = {
zoom: 12,
center: center,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
for (i = 0; i < markers1.length; i++) {
addMarker(markers1[i]);
}
}
/**
* Function to add marker to map
*/
function addMarker(marker) {
var category = marker[4];
var title = marker[1];
var pos = new google.maps.LatLng(marker[2], marker[3]);
var content = marker[1];
var fullContent = marker.slice(1,6).join();
var marker1 = new google.maps.Marker({
title: title,
position: pos,
category: category,
map: map
});
gmarkers1.push(marker1);
// Marker click listener
google.maps.event.addListener(marker1, 'click', (function (marker1, fullContent) {
return function () {
console.log('Gmarker 1 gets pushed');
infowindow.setContent(fullContent);
infowindow.open(map, marker1);
map.panTo(this.getPosition());
map.setZoom(15);
///////
// Set CSS for the control border.
var controlDiv = document.createElement("div");
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = '#fff';
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '22px';
controlUI.style.textAlign = 'center';
controlUI.title = 'Click to recenter the map';
controlDiv.appendChild(controlUI);
// Set CSS for the control interior.
var controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '16px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = 'Center Map';
controlUI.appendChild(controlText);
// Setup the click event listeners: simply set the map to Chicago.
controlUI.addEventListener('click', function() {
//Do Whatever you want here
});
controlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_CENTER].push(controlDiv);
///////
}
})(marker1, fullContent));
}
/**
* Function to filter markers by category
*/
filterMarkers = function (category) {
for (i = 0; i < markers1.length; i++) {
marker = gmarkers1[i];
// If is same category or category not picked
if (marker.category == category || category.length === 0) {
marker.setVisible(true);
}
// Categories don't match
else {
marker.setVisible(false);
}
}
}
// Init map
initialize();
#map-canvas {
width: 500px;
height: 500px;
}
<div id="map-canvas"></div>
<select id="type" onchange="filterMarkers(this.value);">
<option value="">Please select category</option>
<option value="second">second</option>
<option value="car">car</option>
<option value="third">third</option>
</select>
if you print our your i in your listener, you will realized it always to be 4. Basically, the listener does not remember the number i, since it is a globe variable.
Look at the Google Example, they called a function and setup the info window inside.(so that it is i independent) You might do the same too.
Another solution is to store the value i as a tag to the marker, so that you can retrieve it from the marker object.

Resources