how to make labels curved in amcharts radar chart - amcharts

i want to curve labels of radar chart as done on pie chart here https://codepen.io/team/amcharts/pen/wNYbbo
how to achieve same curved lables on this radarchart
below is the code snippets of my radar chart
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#chartdiv {
width: 100%;
height: 600px;
}
am4core.useTheme(am4themes_animated);
// Themes end
var chart = am4core.create("chartdiv", am4charts.RadarChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.data = [
{
category: "Happiness",
value1: 8,
"config":{"fill": "red"},
"background": {"fill":"green"}
},
{
category: "Anxiety",
value1: 9,
"config":{"fill": "blue"}
},
{
category: "Three",
value1: 7,
"config":{"fill": "green"}
},
{
category: "Four",
value1: 1,
"config":{"fill": "red"}
},
{
category: "Five",
value1: 2,
"config":{"fill": "orange"}
},
{
category: "Six",
value1: 5,
value2: -5,
"config":{"fill": "black"}
}
];
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.labels.template.location = 0.5;
categoryAxis.renderer.tooltipLocation = 0.5;
categoryAxis.renderer.cellStartLocation = 0;
categoryAxis.renderer.cellEndLocation = 1;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.renderer.labels.template.horizontalCenter = "left";
valueAxis.min = 0;
var series1 = chart.series.push(new am4charts.RadarColumnSeries());
series1.columns.template.tooltipText = "{category}: {valueY.value}";
series1.columns.template.width = am4core.percent(100);
series1.name = "Series 1";
series1.dataFields.categoryX = "category";
series1.dataFields.valueY = "value1";
series1.columns.template.radarColumn.configField = 'config';
chart.seriesContainer.zIndex = -1;
chart.scrollbarX = new am4core.Scrollbar();
chart.scrollbarX.exportable = false;
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.exportable = false;
chart.cursor = new am4charts.RadarCursor();
chart.cursor.xAxis = categoryAxis;
chart.cursor.fullWidthXLine = true;
chart.cursor.lineX.strokeOpacity = 0;
chart.cursor.lineX.fillOpacity = 0.1;
https://codepen.io/omar630/pen/KKWWbNe?editors=0010
here is the codepen link
just need labels curved on outside of respective area sections

var chart = am4core.create("chartdiv", am4charts.RadarChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.data = [
{
category: "Happiness",
value1: 8,
"config":{"fill": "red"},
"background": {"fill":"green"}
},
{
category: "Anxiety",
value1: 9,
"config":{"fill": "blue"}
},
{
category: "Three",
value1: 7,
"config":{"fill": "green"}
},
{
category: "Four",
value1: 1,
"config":{"fill": "red"}
},
{
category: "Five",
value1: 2,
"config":{"fill": "orange"}
},
{
category: "Six",
value1: 5,
value2: -5,
"config":{"fill": "black"}
}
];
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.labels.template.location = 0.5;
categoryAxis.renderer.tooltipLocation = 0.5;
categoryAxis.renderer.cellStartLocation = 0;
categoryAxis.renderer.cellEndLocation = 1;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.renderer.labels.template.horizontalCenter = "left";
valueAxis.min = 0;
var series1 = chart.series.push(new am4charts.RadarColumnSeries());
series1.columns.template.tooltipText = "{category}: {valueY.value}";
series1.columns.template.width = am4core.percent(100);
series1.name = "Series 1";
series1.dataFields.categoryX = "category";
series1.dataFields.valueY = "value1";
series1.columns.template.radarColumn.configField = 'config';
chart.seriesContainer.zIndex = -1;
chart.scrollbarX = new am4core.Scrollbar();
chart.scrollbarX.exportable = false;
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.exportable = false;
chart.cursor = new am4charts.RadarCursor();
chart.cursor.xAxis = categoryAxis;
chart.cursor.fullWidthXLine = true;
chart.cursor.lineX.strokeOpacity = 0;
chart.cursor.lineX.fillOpacity = 0.1;
//add below lines in your code
categoryAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) {
var value = target.dataItem.category;
var position = categoryAxis.categoryToPosition(value);
var angle = categoryAxis.renderer.positionToAngle(position) + 90;
return angle;
});
Try this it will work check bottom lines which are added.

found solution here is the snippet
am4core.ready(function () {
// the chart
var chart = am4core.create("amchart_wheel_of_life", am4charts.RadarChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
chart.innerRadius = am4core.percent(30);
chart.width = am4core.percent(100);
chart.height = am4core.percent(100);
chart.seriesContainer.zIndex = -1; // grid over series
//chart.seriesContainer.background.fill = '#0f0'
//chart.seriesContainer.opacity = 0.5
//chart.padding(20, 20, 20, 20);
// chart data
var wheel_data = [
{
'range': 'another',
'data': [{
"category": "another",
"value": 10,
"color": chart.colors.next(),
}]
},{
'range': 'Your hapsadpiness',
'data': [{
"category": "your haasdppiness",
"value": 10,
"color": chart.colors.next(),
}]
},{
'range': 'Your happiness',
'data': [{
"category": "your happiness",
"value": 10,
"color": chart.colors.next(),
}]
}, {
'range': 'Self Esteem',
'data': [{
"category": "self esteem",
"value": 6,
"color": chart.colors.next()
}]
}, {
'range': 'Your Mood',
'data': [{
"category": "your mood",
"value": 3,
"color": chart.colors.next()
}]
}, {
'range': 'Digital Usage',
'data': [{
"category": "digial usage",
"value": 7,
"color": chart.colors.next()
}]
}, {
'range': 'Job Satisfaction',
'data': [{
"category": "Job Satisfaction",
"value": 9,
"color": chart.colors.next()
}]
}, {
'range': 'your calmness',
'data': [{
"category": "sad",
"value": 5,
"color": chart.colors.next()
}]
}, {
'range': 'stress level',
'data': [{
"category": "stress level",
"value": 2,
"color": chart.colors.next()
}]
}];
// interaction
var categoryIndex = 0;
chart.cursor = new am4charts.RadarCursor();
chart.cursor.innerRadius = am4core.percent(25);
chart.cursor.behavior = "none"; // disable zoom
//chart.cursor.lineX.disabled = true;
//chart.cursor.lineY.fillOpacity = 0.1;
//chart.cursor.lineY.fill = am4core.color("#000000");
//chart.cursor.lineY.strokeOpacity = 0;
//chart.cursor.fullWidthLineY = true;
chart.cursor.events.on("cursorpositionchanged", function (ev) { // up
var xAxis = ev.target.chart.xAxes.getIndex(0);
var yAxis = ev.target.chart.yAxes.getIndex(0);
categoryIndex = xAxis.positionToIndex(xAxis.toAxisPosition(ev.target.xPosition));
//console.log(yAxis.toAxisPosition(ev.target.yPosition));
//console.log("y: ", yAxis.positionToValue(yAxis.toAxisPosition(ev.target.yPosition)));
});
// var interaction = am4core.getInteraction();
// interaction.events.on("up", function (event) {
// var point = am4core.utils.documentPointToSprite(event.pointer.point, chart.seriesContainer);
// var empty = 4.2;
// var x = (valueAxis.max + empty) - valueAxis.xToValue(point.x);
// var y = (valueAxis.max + empty) - valueAxis.yToValue(point.y);
// var r = Math.sqrt(x * x + y * y) - empty;
// //console.log(x,y,r);
// if (r > valueAxis.min - 1 && r < valueAxis.max) {
// //console.log(r);
// setValue(categoryIndex, Math.ceil(r));
// }
// });
// set value
function setValue(index, value) {
chart.data[index].value = value;
chart.invalidateRawData();
}
// categoryAxis
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
// categoryAxis.renderer.lebels.template.background = 'black';
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.labels.template.location = 0.5;
categoryAxis.renderer.tooltipLocation = 0.5;
categoryAxis.renderer.labels.template.bent = true;
categoryAxis.renderer.labels.template.padding(0, 0, 0, 0);
categoryAxis.renderer.labels.template.fill = am4core.color("#414042");
// categoryAxis.renderer.fill = am4core.color('red')
categoryAxis.renderer.labels.template.disabled = true; //hide label name
categoryAxis.renderer.grid.template.strokeDasharray = "1,2"
categoryAxis.renderer.labels.template.adapter.add("radius", (innerRadius, target) => {
return -valueAxis.valueToPoint(-3.8).y;
});
categoryAxis.tooltip.defaultState.properties.opacity = 0.; // hide tooltip
/*categoryAxis.renderer.axisFills.template.disabled = false;
categoryAxis.renderer.axisFills.template.fillOpacity = 1;
categoryAxis.renderer.axisFills.template.fill = am4core.color("#e7e8e8");
*/
// valueAxis
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
//valueAxis.renderer.labels.template.disabled = true;
valueAxis.renderer.labels.template.fill = am4core.color("#414042");
valueAxis.min = 0;
valueAxis.max = 10;
valueAxis.renderer.minGridDistance = 10;
valueAxis.fontSize = '10px';
// valueAxis.renderer.labels.template.adapter.add("dy", (innerRadius, target) => {
// return -valueAxis.valueToPoint(-3.7).y;
// });
// series
var series = chart.series.push(new am4charts.RadarColumnSeries());
series.columns.template.width = am4core.percent(100);
series.columns.template.strokeWidth = 0;
series.columns.template.column.propertyFields.fill = "color";
series.dataFields.categoryX = "category";
series.dataFields.valueY = "value";
// series tootltip
series.columns.template.tooltipText = "{categoryX}: {valueY.value}";
series.tooltip.getFillFromObject = false;
series.tooltip.background.fill = am4core.color("#f7aa00");
series.tooltip.label.fill = am4core.color("#414042");
series.tooltip.label.fontWeight = 'bold';
series.tooltip.background.strokeOpacity = 0;
// center image
var image = categoryAxis.createChild(am4core.Image);
image.horizontalCenter = "middle";
image.verticalCenter = "middle";
image.href = "https://happimynd.com/images/icons/icon-512x512.png";
image.width = am4core.percent(23);
image.height = am4core.percent(23);
// image.zIndex = 1; // grid over series
var circle = chart.seriesContainer.createChild(am4core.Circle);
circle.horizontalCenter = "middle";
circle.verticalCenter = "middle";
circle.fill = am4core.color('#e7e8e8');
circle.zIndex = -5; // grid over seriesd
categoryAxis.events.on('sizechanged', (ev) => {
circle.radius = -valueAxis.valueToPoint(11.5).y;
});
function generateRadarData() {
let data = [];
for (let i in wheel_data) {
// capitalize
for (let t in wheel_data[i].data) {
wheel_data[i].data[t].category = wheel_data[i].data[t].category.toUpperCase();
}
data = data.concat(wheel_data[i].data);
createRange(wheel_data[i].range, wheel_data[i].data, i);
}
//console.log(data);
return data;
}
function createRange(name, data, index) {
let axisRange = categoryAxis.axisRanges.create();
axisRange.text = name.toUpperCase();
// first country
axisRange.category = data[0].category;
// last country
axisRange.endCategory = data[data.length - 1].category;
// range grid
//axisRange.grid.disabled = true;
axisRange.label.mouseEnabled = false;
axisRange.grid.stroke = am4core.color("#FFFFFF");
axisRange.grid.strokeWidth = 1;
axisRange.grid.strokeOpacity = 1;
axisRange.grid.strokeDasharray = "0,0";
axisRange.grid.adapter.add("radius", (innerRadius, target) => {
return -valueAxis.valueToPoint(13.8).y;
});
// range background
let axisFill = axisRange.axisFill;
axisFill.fill = data[0].color; // chart.colors.next
axisFill.disabled = false;
axisFill.fillOpacity = 1;
axisFill.adapter.add("innerRadius", (innerRadius, target) => {
return -valueAxis.valueToPoint(11.5).y;
});
axisFill.adapter.add("radius", (innerRadius, target) => {
return -valueAxis.valueToPoint(13.8).y;
});
//axisFill.togglable = true;
//axisFill.showSystemTooltip = true;
//axisFill.readerTitle = "click to zoom";
//axisFill.cursorOverStyle = am4core.MouseCursorStyle.pointer;
// range label
let axisLabel = axisRange.label;
axisLabel.location = 0.5;
axisLabel.fill = am4core.color("#414042");
axisLabel.fontWeight = 'bold';
axisLabel.fontSize = '10px';
axisLabel.adapter.add("radius", (innerRadius, target) => {
return -valueAxis.valueToPoint(-1.9).y;
});
}
chart.data = generateRadarData();
});
#amchart_wheel_of_life {
width: 100%;
height: 98vh;
font-family:arial;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="amchart_wheel_of_life"></div>
https://codepen.io/omar630/pen/YzZVVGr

Related

Amcharts: Multiple category axis grid alignment issue in Column series chart

I am trying to create horizontal column series chart having multiple category axis.
Both categories are not aligned with same grid lines.
I am tried below but still same issue.
categoryAxis1.syncWithAxis = categoryAxis;
Need help to resolve this.
Please refer below link
https://jsfiddle.net/8e0hqa6b/2/
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.padding(40, 40, 40, 40);
chart.topAxesContainer.layout = "horizontal";
chart.topAxesContainer.reverseOrder = false;
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
/* categoryAxis.renderer.grid.template.location = 0; */
categoryAxis.dataFields.category = "network";
/* categoryAxis.renderer.minGridDistance = 1; */
categoryAxis.renderer.inversed = true;
categoryAxis.renderer.grid.template.disabled = true;
categoryAxis.layout = "absolute";
categoryAxis.renderer.labels.template.align = 'left';
// Set up axis title
categoryAxis.title.text = "Accounts";
categoryAxis.title.rotation = 0;
categoryAxis.title.align = "left";
categoryAxis.title.valign = "top";
categoryAxis.title.dy = -22;
categoryAxis.title.fontWeight = 500;
var categoryAxis1 = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis1.dataFields.category = "MAU1";
categoryAxis1.renderer.inversed = true;
categoryAxis1.renderer.grid.template.disabled = true;
categoryAxis1.layout = "absolute";
categoryAxis1.renderer.labels.template.align = 'right';
categoryAxis1.syncWithAxis = categoryAxis;
// Set up axis title
categoryAxis1.title.text = "Amount";
categoryAxis1.title.rotation = 0;
categoryAxis1.title.align = "right";
categoryAxis1.title.valign = "top";
categoryAxis1.title.dy = -22;
categoryAxis1.title.fontWeight = 500;
var interfaceColors = new am4core.InterfaceColorSet();
var positiveColor = interfaceColors.getFor("positive");
var negativeColor = interfaceColors.getFor("negative");
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.opposite = true;
valueAxis.min = 0;
valueAxis.renderer.labels.template.disabled = true;
valueAxis.renderer.grid.template.disabled = true;
valueAxis.renderer.baseGrid.disabled = true;
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.categoryY = "network";
series.dataFields.valueX = "MAU";
series.yAxis = categoryAxis;
series.tooltipText = "{valueX.value}"
series.columns.template.strokeOpacity = 0;
series.columns.template.column.cornerRadiusBottomRight = 2;
series.columns.template.column.cornerRadiusTopRight = 2;
/* series.columns.template.column.dy = -6 */
var series1 = chart.series.push(new am4charts.ColumnSeries());
series1.dataFields.categoryY = "MAU1";
series1.dataFields.valueX = "MAU";
series1.yAxis = categoryAxis1;
series1.tooltipText = "{valueX.value}"
series1.columns.template.disabled = true;
// as by default columns of the same series are of the same color, we add adapter which takes colors from chart.colors color set
/* series.columns.template.adapter.add("fill", function(fill, target){
return chart.colors.getIndex(target.dataItem.index);
}); */
/* categoryAxis1.sortBySeries = series; */
/* categoryAxis.sortBySeries = series; */
chart.data = [{
"network": "Facebook",
"MAU": 2255250000,
"MAU1": 2255250000
},
{
"network": "Google+",
"MAU": 430000000,
"MAU1": 430000000
},
{
"network": "Instagram",
"MAU": 1000000000,
"MAU1": 1000000000
},
{
"network": "Pinterest",
"MAU": 246500000,
"MAU1": 246500000
},
{
"network": "Reddit",
"MAU": 355000000,
"MAU1": 355000000
},
{
"network": "TikTok",
"MAU": 500000000,
"MAU1": 500000000
},
{
"network": "Tumblr",
"MAU": 624000000,
"MAU1": 624000000
},
{
"network": "Twitter",
"MAU": 329500000,
"MAU1": 329500000
},
{
"network": "WeChat",
"MAU": 1000000000,
"MAU1": 1000000000
}
]

I want to change this vertical image slider to horizontal one

This is the current vertical image slider URL.
current vertical image slider URL.
I want to change the slider direction to horizontal.
These are my codes.
right view.js
import { View } from './view.js'
class SliderAnimator {
// Ramon: Frame count of animation
static MAX_COUNT = 50
constructor(view) {
this.view = view
this.running = false
this.view.plane.children[0].material.uniforms.hidden.value = false
}
update() {
if (this.running) {
this.stepCount++
this.view.divider = this.from + (this.to - this.from) /
SliderAnimator.MAX_COUNT * this.stepCount
// this.view.plane.children[0].material.uniforms.divider.value = this.view.divider
// this.view.plane.children[0].material.uniforms.hidden.value = false
if (this.stepCount == SliderAnimator.MAX_COUNT) {
this.running = false
// this.view.plane.children[0].material.uniforms.hidden.value = true
}
}
}
}
export class TopRightView extends View {
static DIVIDER_THRESHOLD = 30
async init() {
await super.init()
let textureLoader = new THREE.TextureLoader()
let texture0 = textureLoader.setPath('./images/jpeg/').load(param.JPEG_FILES[this.id])
let texture1 = textureLoader.setPath('./images/jpeg/').load(param.JPEG_FILES[4])
this.plane.children[0].material = new THREE.ShaderMaterial({
uniforms: {
divider: { value: 0 },
hidden: {value: true },
zoomFactor: { value: 1.0 },
tex0: { type: "t", value: texture0 },
tex1: { type: "t", value: texture1 }
},
vertexShader: this.vertexShader(),
fragmentShader: this.fragmentShader()
})
// this.divider = this.planeWidth / 2
this.divider = 0
this.plane.children[0].material.uniforms.divider.value = this.divider
// this.plane.children[0].material.uniforms.divider.value = 1.3333
this.dividerMoving = false
this.snappable = false
this.sliderAnimator = new SliderAnimator(this)
}
vertexShader() {
return `
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vUv = uv;
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
}
fragmentShader() {
return `
varying vec2 vUv;
varying vec3 vPosition;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float divider;
uniform float zoomFactor;
uniform bool hidden;
void main() {
float dividerWidth;
if (hidden) {
dividerWidth = 0.0;
} else {
dividerWidth = 0.03 / zoomFactor;
}
if (vPosition.x > divider + dividerWidth) {
gl_FragColor = texture2D(tex1, vUv);
} else if (vPosition.x < divider - dividerWidth) {
gl_FragColor = texture2D(tex0, vUv);
} else {
gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);
}
}
`
}
}
views.js
import { SVGPlane } from './svg-plane.js';
export class View {
static DRAG_TRESHOLD = 3;
constructor(id, containter, vector, elementControl) {
this.id = id;
this.width = window.innerWidth - 2 * param.cLeft;
this.height = param.cHeight * 2 + param.cTop;
this.container = containter;
this.vector = vector;
this.elementControl = elementControl;
this.mouseDownPosition = new THREE.Vector2();
}
async init() {
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setSize(this.width, this.height);
this.container.appendChild(this.renderer.domElement);
// this.renderer.setClearColor(param.BACK_COLORS[this.id], 0);
this.camera = new THREE.OrthographicCamera(
param.orthoWidth / (-2),
param.orthoWidth / 2,
param.orthoHeight / 2,
param.orthoHeight / (-2),
0.05, 1000
);
this.camera.position.fromArray(param.CAMERA_POSITIONS[this.id]);
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(param.BACK_COLORS[this.id]);
this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
this.controls.enableRotate = false;
await this._initMeshes();
this._calibrateCamera();
this.animate();
this.container.addEventListener('mousemove', (event) => { this.onMouseMove(event) }, false);
this.container.addEventListener('mousedown', (event) => { this.onMouseDown(event) }, false);
this.container.addEventListener('mouseup', (event) => { this.onMouseUp(event) }, false);
this.container.addEventListener('mouseout', (event) => { this.onMouseUp(event) }, false);
this.renderer.domElement.addEventListener(
'wheel', (event) => { this.onWheel(event) }, false
);
}
_calibrateCamera() {
this.camera.left = -this.planeWidth / 2;
this.camera.right = this.planeWidth / 2;
this.camera.top = this.planeWidth / 2 * this.height / this.width;
this.camera.bottom = -this.camera.top;
this.camera.updateProjectionMatrix();
}
async _initMeshes() {
this.plane = new THREE.Group();
var imageMesh = await this._getImageMesh();
imageMesh.name = "plane";
this.plane.add(imageMesh);
var helper = new THREE.GridHelper(400, 800);
helper.material.opacity = 0.75;
helper.material.transparent = true;
helper.material.depthTest = false;
helper.position.y = 0.1;
this.plane.add(helper);
this.plane.rotation.fromArray(param.PLANE_ROTATIONS[this.id]);
this.scene.add(this.plane);
}
async _getImageMesh() {
if (param.SVG_MODE) {
return await new SVGPlane().createSVGPlane(param.SVG_FILES[this.id]);
} else {
return new Promise((resolve, reject) => {
new THREE.TextureLoader().setPath('./images/jpeg/').load(
param.JPEG_FILES[this.id],
(t) => {
var s = param.JPEG_SCALES[this.id];
this.planeWidth = s * param.pLength;
this.planeHeight = s * param.pLength * t.image.height / t.image.width;
console.log(this.planeWidth, this.planeHeight);
var planeGeo = new THREE.BoxGeometry(
this.planeWidth, 0.01, this.planeHeight
);
var planeMat = new THREE.MeshPhongMaterial({ map: t });
var planeMesh = new THREE.Mesh(planeGeo, planeMat);
planeMesh.position.copy(param.JPEG_OFFSETS[this.id]);
resolve(planeMesh);
});
});
}
}
animate() {
window.requestAnimationFrame(() => { this.animate(); });
this.renderer.clear();
this.renderer.render(this.scene, this.camera);
}
}
parameter.js
class Parameter {
TOP_LEFT = 0;
TOP_RIGHT = 1;
BOTTOM_LEFT = 2;
BOTTOM_RIGHT = 3;
TO_METER = 0.3048;
PLANE_COLOR = 0xaaaaaa;
BALL_COLOR = 0x0000ff;
LINE_COLOR = 0xff0000;
BACK_COLORS = [
0x598d4b,
0x598d4b,
0xc6ced1,
0xc6ced1
];
MAP_SCALE = 100 / 1.5 * 100 / 53; // no meaning anymore
SVG_MODE = false;
JPEG_FILES = [
'1-Top-Left-Quadrant.jpg',
'2-Top-Right-Quadrant.jpg',
'3-Bottom-Left-Quadrant.jpg',
'4-Bottom-Right-Quadrant.jpg',
'2-Top-Right-Quadrant-2.jpg'
];
SVG_FILES = [
'1-Top-Left-Quadrant.svg',
'2-Top-Right-Quadrant.svg',
'3-Bottom-Left-Quadrant.svg',
'4-Bottom-Right-Quadrant.svg'
];
CAMERA_POSITIONS = [
[ -5, 5, 5],
[ 0, 10, 0],
[-10, 0, 0],
[ 0, 0, 10]
];
PLANE_ROTATIONS = [
[0, 0, 0],
[0, 0, 0],
[Math.PI / 2, 0, Math.PI / 2],
[Math.PI / 2, 0, 0]
];
// PLANE_AXES = ['', 'xz', 'yz', 'xy'];
JPEG_SCALES = [0.8267, 1, 0.95, 0.5688];
JPEG_OFFSETS = [
new THREE.Vector3(0.4, 0, -0.3),
new THREE.Vector3(),
new THREE.Vector3(0, 0, -0.73),
new THREE.Vector3(0.9, 0, -0.98),
];
CAMERA_OFFSETS = [
this.JPEG_OFFSETS[0],
this.JPEG_OFFSETS[1],
new THREE.Vector3(-this.JPEG_OFFSETS[2].z, 0, this.JPEG_OFFSETS[2].x),
new THREE.Vector3(this.JPEG_OFFSETS[3].x, 0, -this.JPEG_OFFSETS[3].z)
]
BALL_SIZE = 0.05;
constructor() {
if (!!Parameter.instance) {
return Parameter.instance;
}
Parameter.instance = this;
this._init();
return this;
}
_init() {
var controlBarHeight = 0;
var gap = 2;
this.cWidth = (window.innerWidth - gap * 3) / 2;
this.cHeight = (window.innerHeight - controlBarHeight - gap * 3) / 2;
this.cTop = gap;
this.cLeft = gap;
this.cRate = this.cWidth / this.cHeight;
this.orthoHeight = 8;
this.orthoWidth = this.orthoHeight * this.cRate;
this.pLength = 8;
this.hLength = 5;
}
}
var param = new Parameter();
Please help me.

Fabric JS 2.4.1 How to use clipPath to crop image that has been scaled smaller or larger then 1:1 Ratio

I have been trying to figure out what I am doing wrong when calculation the position and size of the mask rectangle once the target image has been resized.
Below is the documentation from fabric JS:
clipPath :fabric.Object
a fabricObject that, without stroke define a clipping area with their shape. filled in black the clipPath object gets used when the object has rendered, and the context is placed in the center of the object cacheCanvas. If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center'
Type:
fabric.Object
Source:
fabric.js, line 12991
The code I have works perfectly when the image is not resized (scale 1:1 X & Y). In the code's function named rescaleMask I attempt to position the mask to a zero center X & Y and when I run my math manually on a piece of graph paper it appears the math is correct. Obviously there is a piece that I am unaware of that is causing the positioning to be off in different ways depending on the quadrant in which the crop is being performed. There is quite a bit of code here but it is important that the mask is created dynamically and not hard coded. The problem must be in the rescaleMask function so hopefully the rest of the code can be ignored.
I created a test image graph with numbered squares which I will crop by clicking the mask button, drawing a rectangle around one of the boxes with the mouse left button and then clicking the crop button. The problem occurs when you resize the image before creating the mask and cropping.
Here is the test image:
Here is a jsfiddle fabric Creating rect with a mouse dynamic js 2.4.1 sent as fix #4
<canvas id="c" width="500" height="500" style="border:1px solid #ccc"></canvas>
<button id="mask">Mask</button>
<button id="crop">Crop</button>
JS
var lastSelectedPicture = null;
var isInsertingCropRectangle = false;
var canvas = new fabric.Canvas('c', {
selection: true,
preserveObjectStacking: true,
height: 700,
width: 800
});
var crop_rect, isDown, origX, origY, mask, target;
var done = false;
var src = "https://stealth-apsvaw.streamhoster.com/fabric_js_2_4_1_crop_test/graph_paper_540.png";
fabric.Image.fromURL(src, function(img) {
img.selectable = true;
img.id = 'target';
img.top = 30;
img.left = 30;
canvas.add(img);
});
canvas.on('object:added', function(e) {
target = null;
mask = null;
canvas.forEachObject(function(obj) {
//alert(obj.get('id'));
var id = obj.get('id');
if (id === 'target') {
target = obj;
canvas.setActiveObject(obj);
}
if (id === 'mask') {
//alert(done);
//alert('mask');
mask = obj;
}
});
});
canvas.on('object:modified', function(e) {
e.target.setCoords();
canvas.renderAll();
});
//////////////////////////////////////////////////////////
// MASK
//////////////////////////////////////////////////////////
document.getElementById("mask").addEventListener("click", function() {
isInsertingCropRectangle = true;
canvas.discardActiveObject();
lastSelectedPicture.selectable = false;
lastSelectedPicture.setCoords();
lastSelectedPicture.dirty = true;
canvas.renderAll();
canvas.discardActiveObject();
isInsertingCropRectangle = true;
});
//////////////////////////////////////////////////////////
// CROP
//////////////////////////////////////////////////////////
document.getElementById("crop").addEventListener("click", function() {
if (target !== null && mask !== null) {
target.setCoords();
// Re-scale mask
mask = rescaleMask(target, mask);
mask.setCoords();
// Do the crop
target.clipPath = mask;
target.dirty=true;
canvas.setActiveObject(target);
canvas.bringToFront(target);
target.selectable = true;
canvas.remove(mask);
canvas.renderAll();
console.log(target);
}
});
//////////////////////////////////////////////////////////
// RE-SCALE MASK FOR CROPPING
// P R O B L E M I N T H I S F U N C T I O N
//////////////////////////////////////////////////////////
function rescaleMask(target, mask){
mask.scaleX = 1;
mask.scaleY = 1;
var targetCenterX = target.width * target.scaleX / 2;
var targetCenterY = target.height * target.scaleY / 2;
var maskOverlapX = mask.left - target.left;
var maskOverlapY = mask.top - target.top;
var centerBasedX = maskOverlapX - targetCenterX;
var centerBasedY = maskOverlapY - targetCenterY;
if( maskOverlapX >= targetCenterX){
centerBasedX = maskOverlapX - targetCenterX;
}
else{
centerBasedX = -(targetCenterX) + maskOverlapX;
}
if( maskOverlapY >= targetCenterY){
centerBasedY = maskOverlapY - targetCenterY;
}
else{
centerBasedY = -(targetCenterY) + maskOverlapY;
}
console.log('targetleft = '+target.left);
console.log('targettop = '+target.top);
console.log('targetCenterX = '+targetCenterX);
console.log('targetCenterY = '+targetCenterY);
console.log('maskleft = '+mask.left);
console.log('masktop = '+mask.top);
console.log('maskOverlapX = '+maskOverlapX);
console.log('maskOverlapY = '+maskOverlapY);
console.log('centerBasedX = '+centerBasedX);
console.log('centerBasedY = '+centerBasedY);
mask.left = centerBasedX;
mask.top = centerBasedY;
mask.originX = 'left';
mask.originY = 'top';
mask.setCoords();
mask.dirty=true;
canvas.renderAll();
//var newMask = mask;
return(mask);
}
canvas.on('mouse:down', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse down done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
crop_rect = new fabric.Rect({
left: origX,
top: origY,
width: pointer.x - origX,
height: pointer.y - origY,
opacity: .3,
transparentCorners: false,
selectable: true,
id: 'mask'
});
canvas.add(crop_rect);
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:move', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse move done = '+done);
if (done) {
canvas.renderAll();
return;
}
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
crop_rect.set({
left: Math.abs(pointer.x)
});
}
if (origY > pointer.y) {
crop_rect.set({
top: Math.abs(pointer.y)
});
}
crop_rect.set({
width: Math.abs(origX - pointer.x)
});
crop_rect.set({
height: Math.abs(origY - pointer.y)
});
crop_rect.setCoords();
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:up', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse up done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = false;
crop_rect.set({
selectable: true
});
done = true;
}
else{
}
});
canvas.on('selection:created', function(event) {
console.log("canvas.on('selection:created'");
selectionChanged(event);
});
canvas.on('selection:updated', function(event) {
console.log("canvas.on('selection:updated'");
selectionChanged(event);
});
function selectionChanged(event){
console.log("selectionChanged");
console.log("selectionChanged type = "+event.target.type);
switch(event.target.type) {
case 'textbox':
break;
case 'image':
lastSelectedPicture = event.target;
break;
case 'rect':
break;
case 'group':
break;
default:
break;
}
}
You need to take in consideration the target.scaleX and target.scaleY for mask.
var lastSelectedPicture = null;
var isInsertingCropRectangle = false;
canvas = new fabric.Canvas('c', {
selection: true,
preserveObjectStacking: true,
height: 700,
width: 800
});
var crop_rect, isDown, origX, origY, mask, target;
var done = false;
var src = "https://stealth-apsvaw.streamhoster.com/fabric_js_2_4_1_crop_test/graph_paper_540.png";
fabric.Image.fromURL(src, function(img) {
img.selectable = true;
img.id = 'target';
img.top = 30;
img.left = 30;
canvas.add(img);
});
canvas.on('object:added', function(e) {
target = null;
mask = null;
canvas.forEachObject(function(obj) {
//alert(obj.get('id'));
var id = obj.get('id');
if (id === 'target') {
target = obj;
canvas.setActiveObject(obj);
}
if (id === 'mask') {
//alert(done);
//alert('mask');
mask = obj;
}
});
});
canvas.on('object:modified', function(e) {
e.target.setCoords();
canvas.renderAll();
});
//////////////////////////////////////////////////////////
// MASK
//////////////////////////////////////////////////////////
document.getElementById("mask").addEventListener("click", function() {
isInsertingCropRectangle = true;
canvas.discardActiveObject();
lastSelectedPicture.selectable = false;
lastSelectedPicture.setCoords();
lastSelectedPicture.dirty = true;
canvas.renderAll();
canvas.discardActiveObject();
isInsertingCropRectangle = true;
});
//////////////////////////////////////////////////////////
// CROP
//////////////////////////////////////////////////////////
document.getElementById("crop").addEventListener("click", function() {
if (target !== null && mask !== null) {
target.setCoords();
// Re-scale mask
mask = rescaleMask(target, mask);
mask.setCoords();
// Do the crop
target.clipPath = mask;
target.dirty=true;
canvas.setActiveObject(target);
canvas.bringToFront(target);
target.selectable = true;
canvas.remove(mask);
canvas.renderAll();
console.log(target);
}
});
//////////////////////////////////////////////////////////
// RE-SCALE MASK FOR CROPPING
// P R O B L E M I N T H I S F U N C T I O N
//////////////////////////////////////////////////////////
function rescaleMask(target, mask){
mask.scaleX = 1;
mask.scaleY = 1;
mask.scaleX/=target.scaleX;
mask.scaleY/=target.scaleY;
var targetCenterX = target.width * target.scaleX / 2;
var targetCenterY = target.height * target.scaleY / 2;
var maskOverlapX = mask.left - target.left;
var maskOverlapY = mask.top - target.top;
var centerBasedX = maskOverlapX - targetCenterX;
var centerBasedY = maskOverlapY - targetCenterY;
if( maskOverlapX >= targetCenterX){
centerBasedX = (maskOverlapX - targetCenterX)/target.scaleX;
}
else{
centerBasedX = (-(targetCenterX) + maskOverlapX)/target.scaleX;
}
if( maskOverlapY >= targetCenterY){
centerBasedY = (maskOverlapY - targetCenterY)/target.scaleY;
}
else{
centerBasedY = (-(targetCenterY) + maskOverlapY)/target.scaleY;
}
console.log('targetleft = '+target.left);
console.log('targettop = '+target.top);
console.log('targetCenterX = '+targetCenterX);
console.log('targetCenterY = '+targetCenterY);
console.log('maskleft = '+mask.left);
console.log('masktop = '+mask.top);
console.log('maskOverlapX = '+maskOverlapX);
console.log('maskOverlapY = '+maskOverlapY);
console.log('centerBasedX = '+centerBasedX);
console.log('centerBasedY = '+centerBasedY);
mask.left = centerBasedX;
mask.top = centerBasedY;
mask.originX = 'left';
mask.originY = 'top';
mask.setCoords();
mask.dirty=true;
canvas.renderAll();
//var newMask = mask;
return(mask);
}
canvas.on('mouse:down', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse down done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
crop_rect = new fabric.Rect({
left: origX,
top: origY,
width: pointer.x - origX,
height: pointer.y - origY,
opacity: .3,
transparentCorners: false,
selectable: true,
id: 'mask'
});
canvas.add(crop_rect);
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:move', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse move done = '+done);
if (done) {
canvas.renderAll();
return;
}
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
crop_rect.set({
left: Math.abs(pointer.x)
});
}
if (origY > pointer.y) {
crop_rect.set({
top: Math.abs(pointer.y)
});
}
crop_rect.set({
width: Math.abs(origX - pointer.x)
});
crop_rect.set({
height: Math.abs(origY - pointer.y)
});
crop_rect.setCoords();
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:up', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse up done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = false;
crop_rect.set({
selectable: true
});
done = true;
}
else{
}
});
canvas.on('selection:created', function(event) {
console.log("canvas.on('selection:created'");
selectionChanged(event);
});
canvas.on('selection:updated', function(event) {
console.log("canvas.on('selection:updated'");
selectionChanged(event);
});
function selectionChanged(event){
console.log("selectionChanged");
console.log("selectionChanged type = "+event.target.type);
switch(event.target.type) {
case 'textbox':
break;
case 'image':
lastSelectedPicture = event.target;
break;
case 'rect':
break;
case 'group':
break;
default:
break;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.1/fabric.min.js"></script>
<canvas id="c" width="500" height="500" style="border:1px solid #ccc"></canvas>
<button id="mask">Mask</button>
<button id="crop">Crop</button>

Multiple Dataset AmstockChart with multiple Axis [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to implement multiple value axis in following amchart sample:
https://www.amcharts.com/demos/multiple-data-sets/
Multiple axis example: http://www.amcharts.com/tips/multiple-value-axes-stock-chart/
I tried a lot but I think I miss some minor thing.
Is there any way to combine above charts (multi value and multi data Set) and create a multiple value axis multiple data sets Chart?
Examples with jsfiddle will work best for me. Thanks :)
I did this myself. Hope this becomes helpful to someone. Here is the solution:
AmCharts.ready(function () {
generateChartData();
createStockChart();
});
var colors = [
"#FF6600", "#B0DE09", "#FCD202", "#2A0CD0",
"#CD0D74", "#CC0000", "#00CC00", "#0000CC", "#DDDDDD",
"#999999", "#333333", "#990000", "#0D8ECF"
];
var chartData1 = [];
var chartData2 = [];
var chartData3 = [];
var chartData4 = [];
function generateChartData() {
var firstDate = new Date();
firstDate.setDate(firstDate.getDate() - 500);
firstDate.setHours(0, 0, 0, 0);
for (var i = 0; i < 500; i++) {
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate()+i);
newDate.setHours(0, 0, 0, 0);
var value1 = Math.round(Math.random() * (40 + i)) + 100 + i;
var value2 = Math.round(Math.random() * (100 + i)) + 200 + i;
var value3 = Math.round(Math.random() * (100 + i)) + 200;
var value4 = Math.round(Math.random() * (100 + i)) + 200 + i;
chartData1.push({date: newDate,value1: value1});
chartData2.push({date: newDate,value2: value2});
chartData3.push({date: newDate,value3: value3});
chartData4.push({date: newDate,value4: value4});
}
}
function createStockChart() {
var chart = new AmCharts.AmStockChart();
chart.pathToImages = "http://www.amcharts.com/lib/3/images/";
var dataSet1 = new AmCharts.DataSet();
dataSet1.fieldMappings = [{fromField: "value1", toField: "value1"}];
dataSet1.dataProvider = chartData1;
dataSet1.categoryField = "date";
dataSet1.title = "Value1";
dataSet1.color = colors[0];
var dataSet2 = new AmCharts.DataSet();
dataSet2.fieldMappings = [{fromField: "value2", toField: "value2"}];
dataSet2.dataProvider = chartData2;
dataSet2.categoryField = "date";
dataSet2.title = "Value2";
dataSet2.color = colors[1];
var dataSet3 = new AmCharts.DataSet();
dataSet3.fieldMappings = [{fromField: "value3", toField: "value3"}];
dataSet3.dataProvider = chartData3;
dataSet3.categoryField = "date";
dataSet3.title = "Value3";
dataSet3.color = colors[2];
var dataSet4 = new AmCharts.DataSet();
dataSet4.fieldMappings = [{fromField: "value4", toField: "value4"}];
dataSet4.dataProvider = chartData4;
dataSet4.categoryField = "date";
dataSet4.title = "Value4";
dataSet4.color = colors[3];
// set data sets to the chart
chart.dataSets = [dataSet1,dataSet2,dataSet3,dataSet4];
// PANELS ///////////////////////////////////////////
// first stock panel
var stockPanel = new AmCharts.StockPanel();
stockPanel.recalculateToPercents = "never";
stockPanel.title = "Volume";
var categoryAxesSettings = new AmCharts.CategoryAxesSettings();
categoryAxesSettings.minPeriod = "DD";
chart.categoryAxesSettings = categoryAxesSettings;
// apply custom style for value axes
var valueAxesSettings = new AmCharts.ValueAxesSettings();
valueAxesSettings.axisAlpha = 1;
valueAxesSettings.gridThickness = 0;
valueAxesSettings.axisThickness = 2;
valueAxesSettings.inside = false;
chart.valueAxesSettings = valueAxesSettings;
// apply custom style for panels settings
var panelsSettings = new AmCharts.PanelsSettings();
panelsSettings.marginLeft = 100;
panelsSettings.marginRight = 100;
chart.panelsSettings = panelsSettings;
// add first value axes
var valueAxis1 = new AmCharts.ValueAxis();
valueAxis1.axisColor = colors[0];
valueAxis1.color = colors[0];
valueAxis1.offset = 0;
stockPanel.addValueAxis(valueAxis1);
// add second value axes
var valueAxis2 = new AmCharts.ValueAxis();
valueAxis2.axisColor = colors[1];
valueAxis2.color = colors[1];
valueAxis2.offset = 0;
valueAxis2.position = "right";
stockPanel.addValueAxis(valueAxis2);
// add third value axes
var valueAxis3 = new AmCharts.ValueAxis();
valueAxis3.axisColor = colors[2];
valueAxis3.color = colors[2];
valueAxis3.offset = 50;
stockPanel.addValueAxis(valueAxis3);
// add fourth value axes
var valueAxis4 = new AmCharts.ValueAxis();
valueAxis4.axisColor = colors[3];
valueAxis4.color = colors[3];
valueAxis4.offset = 50;
valueAxis4.position = "right";
stockPanel.addValueAxis(valueAxis4);
// graph of first stock panel
var graph1 = new AmCharts.StockGraph();
graph1.valueField = "value1";
graph1.comparable = true;
graph1.title = "Value1";
graph1.useDataSetColors = false;
graph1.lineColor = colors[0];
graph1.bullet = "round";
graph1.bulletBorderColor = "#FFFFFF";
graph1.bulletBorderAlpha = 1;
graph1.balloonText = "[[title]]:<b>[[value]]</b>";
graph1.compareGraphBalloonText = "[[title]]:<b>[[value]]</b>";
graph1.compareGraphBullet = "round";
graph1.compareGraphBulletBorderColor = "#FFFFFF";
graph1.compareGraphBulletBorderAlpha = 1;
graph1.valueAxis = valueAxis1;
stockPanel.addStockGraph(graph1);
// graph of second stock panel
var graph2 = new AmCharts.StockGraph();
graph2.valueField = "value2";
graph2.comparable = true;
graph2.title = "Value2";
graph2.useDataSetColors = false;
graph2.lineColor = colors[1];
graph2.bullet = "round";
graph2.bulletBorderColor = "#FFFFFF";
graph2.bulletBorderAlpha = 1;
graph2.balloonText = "[[title]]:<b>[[value]]</b>";
graph2.compareGraphBalloonText = "[[title]]:<b>[[value]]</b>";
graph2.compareGraphBullet = "round";
graph2.compareGraphBulletBorderColor = "#FFFFFF";
graph2.compareGraphBulletBorderAlpha = 1;
graph2.valueAxis = valueAxis2;
stockPanel.addStockGraph(graph2);
// graph of third stock panel
var graph3 = new AmCharts.StockGraph();
graph3.valueField = "value3";
graph3.comparable = true;
graph3.title = "Value3";
graph3.useDataSetColors = false;
graph3.lineColor = colors[2];
graph3.bullet = "round";
graph3.bulletBorderColor = "#FFFFFF";
graph3.bulletBorderAlpha = 1;
graph3.balloonText = "[[title]]:<b>[[value]]</b>";
graph3.compareGraphBalloonText = "[[title]]:<b>[[value]]</b>";
graph3.compareGraphBullet = "round";
graph3.showEventsOnComparedGraphs = true;
graph3.compareGraphBulletBorderColor = "#FFFFFF";
graph3.compareGraphBulletBorderAlpha = 1;
graph3.valueAxis = valueAxis3;
stockPanel.addStockGraph(graph3);
// graph of fourth stock panel
var graph4 = new AmCharts.StockGraph();
graph4.comparable = true;
graph4.valueField = "value4";
graph4.title = "Value4";
graph4.useDataSetColors = false;
graph4.lineColor = colors[3];
graph4.bullet = "round";
graph4.bulletBorderColor = "#FFFFFF";
graph4.bulletBorderAlpha = 1;
graph4.balloonText = "[[title]]:<b>[[value]]</b>";
graph4.compareGraphBalloonText = "[[title]]:<b>[[value]]</b>";
graph4.compareGraphBullet = "round";
graph4.compareGraphBulletBorderColor = "#FFFFFF";
graph4.compareGraphBulletBorderAlpha = 1;
graph4.valueAxis = valueAxis4;
stockPanel.addStockGraph(graph4);
// create stock legend
var stockLegend1 = new AmCharts.StockLegend();
stockLegend1.periodValueTextComparing = "[[percents.value.close]]%";
stockLegend1.periodValueTextRegular = "[[value.close]]";
stockPanel.stockLegend = stockLegend1;
var periodSelector = new AmCharts.PeriodSelector();
periodSelector.periods = [
{period: "DD",count: 5,label: "5 day"},{period: "DD",count: 10,label: "10 days"},
{period: "MM",count: 1,label: "1 month",selected: true}, {period: "YYYY",count: 1,label: "1 year"},
{period: "YTD",label: "YTD"}, {period: "MAX",label: "MAX"}];
periodSelector.position = "left";
chart.periodSelector = periodSelector;
// DATA SET SELECTOR
var dataSetSelector = new AmCharts.DataSetSelector();
dataSetSelector.position = "left";
chart.dataSetSelector = dataSetSelector;
// set panels to the chart
chart.panels = [stockPanel];
// OTHER SETTINGS ////////////////////////////////////
var sbsettings = new AmCharts.ChartScrollbarSettings();
sbsettings.backgroundColor = "#222";
sbsettings.selectedBackgroundColor = "#555";
sbsettings.selectedGraphFillAlpha = 1;
chart.chartScrollbarSettings = sbsettings;
var chartScrollbar = new AmCharts.ChartScrollbar();
chartScrollbar.autoGridCount = true;
chartScrollbar.scrollbarHeight = 40;
chart.chartScrollbar = chartScrollbar;
// CURSOR settings
var cursorSettings = new AmCharts.ChartCursorSettings();
cursorSettings.valueBalloonsEnabled = true;
cursorSettings.cursorAlpha = 0.5;
cursorSettings.valueLineBalloonEnabled = true;
cursorSettings.valueLineEnabled = true;
cursorSettings.valueLineAlpha = 0.5;
cursorSettings.cursorPosition = "mouse";
chart.chartCursorSettings = cursorSettings;
var categoryAxis = new AmCharts.CategoryAxis();
chart.categoryAxis = categoryAxis;
chart.write('chartdiv');
}
body{
font-size:12px;
color:#000000;
background-color:#ffffff;
font-family:verdana,helvetica,arial,sans-serif;
}
.amChartsButtonSelected{
background-color:#CC0000;
border-style:solid;
border-color:#CC0000;
border-width:1px;
color:#FFFFFF;
-moz-border-radius: 5px;
border-radius: 5px;
margin: 1px;
}
.amChartsButton{
background-color:#EEEEEE;
border-style:solid;
border-color:#CCCCCC;
border-width:1px;
color:#000000;
-moz-border-radius: 5px;
border-radius: 5px;
margin: 1px;
}
.amChartsCompareList{
border-style:solid;
border-color:#CCCCCC;
border-width:1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://www.amcharts.com/lib/3/amcharts.js" type="text/javascript"></script>
<script src="http://www.amcharts.com/lib/3/serial.js" type="text/javascript"></script>
<script src="http://www.amcharts.com/lib/3/amstock.js" type="text/javascript"></script>
<div id="chartdiv" style="width: 100%; height: 500px;"></div>

leaflet Dynamic icon with filter

I'm trying to create an map with the leaflet-simple-csv-master (i'm a beginner). It's really nice and i'd like to show different icons with my types (for exemple 1 icon for schools, one for administrations,...). I succed to show my different icons when i have the map but when i click to the filter, my icons disappear. In fact it doesn't work because it do not recognize my variable when i use the filter and i can read that my img is no more logos/type1.png but logos/undefined.png.
This is my all code.
var basemap = new L.TileLayer(baseUrl, {maxZoom: 17, attribution: baseAttribution, subdomains: subdomains, opacity: opacity});
var center = new L.LatLng(0, 0);
var map = new L.Map('map', {center: center, zoom: 2, maxZoom: maxZoom, layers: [basemap]});
var popupOpts = {
autoPanPadding: new L.Point(5, 50),
autoPan: true
};
var points = L.geoCsv (null, {
firstLineTitles: true,
fieldSeparator: fieldSeparator,
onEachFeature: function (feature, layer) {
var popup = '<div class="popup-content"><table class="table table-striped table-condensed">';
for (var clave in feature.properties) {
var title = points.getPropertyTitle(clave).strip();
var attr = feature.properties[clave];
if (title == labelColumn) {
layer.bindLabel(feature.properties[clave], {className: 'map-label'});
}
if (attr.indexOf('http') === 0) {
attr = '<a target="_blank" href="' + attr + '">'+ attr + '</a>';
}
if (attr) {
popup += '<tr><th>'+title+'</th><td>'+ attr +'</td></tr>';
}
}
popup += "</table></popup-content>";
layer.bindPopup(popup, popupOpts);
},
pointToLayer: function (feature, latlng) {
var logo = feature.properties['type'];
return L.marker(latlng, {
icon:L.icon({
iconUrl: 'logos/'+logo+'.png',
shadowUrl: 'marker-shadow.png',
iconSize: [25,41],
shadowSize: [41, 41],
shadowAnchor: [13, 20]
})
});
},
filter: function(feature, layer) {
total += 1;
if (!filterString) {
hits += 1;
return true;
}
var hit = false;
var lowerFilterString = filterString.toLowerCase().strip();
$.each(feature.properties, function(k, v) {
var value = v.toLowerCase();
if (value.indexOf(lowerFilterString) !== -1) {
hit = true;
hits += 1;
return false;
}
});
return hit;
}
});
var hits = 0;
var total = 0;
var filterString;
var markers = new L.MarkerClusterGroup();
var dataCsv;
var addCsvMarkers = function() {
hits = 0;
total = 0;
filterString = document.getElementById('filter-string').value;
if (filterString) {
$("#clear").fadeIn();
} else {
$("#clear").fadeOut();
}
map.removeLayer(markers);
points.clearLayers();
markers = new L.MarkerClusterGroup(clusterOptions);
points.addData(dataCsv);
markers.addLayer(points);
map.addLayer(markers);
try {
var bounds = markers.getBounds();
if (bounds) {
map.fitBounds(bounds);
}
} catch(err) {
// pass
}
if (total > 0) {
$('#search-results').html("Showing " + hits + " of " + total);
}
return false;
};
var typeAheadSource = [];
function ArrayToSet(a) {
var temp = {};
for (var i = 0; i < a.length; i++)
temp[a[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
}
function populateTypeAhead(csv, delimiter) {
var lines = csv.split("\n");
for (var i = lines.length - 1; i >= 1; i--) {
var items = lines[i].split(delimiter);
for (var j = items.length - 1; j >= 0; j--) {
var item = items[j].strip();
item = item.replace(/"/g,'');
if (item.indexOf("http") !== 0 && isNaN(parseFloat(item))) {
typeAheadSource.push(item);
var words = item.split(/\W+/);
for (var k = words.length - 1; k >= 0; k--) {
typeAheadSource.push(words[k]);
}
}
}
}
}
if(typeof(String.prototype.strip) === "undefined") {
String.prototype.strip = function() {
return String(this).replace(/^\s+|\s+$/g, '');
};
}
map.addLayer(markers);
$(document).ready( function() {
$.ajax ({
type:'GET',
dataType:'text',
url: dataUrl,
contentType: "text/csv; charset=utf-8",
error: function() {
alert('Error retrieving csv file');
},
success: function(csv) {
dataCsv = csv;
populateTypeAhead(csv, fieldSeparator);
typeAheadSource = ArrayToSet(typeAheadSource);
$('#filter-string').typeahead({source: typeAheadSource});
addCsvMarkers();
}
});
$("#clear").click(function(evt){
evt.preventDefault();
$("#filter-string").val("").focus();
addCsvMarkers();
});
});

Resources