I want to change this vertical image slider to horizontal one - three.js

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.

Related

Why isn't the camera moving in three.js?

I have create a child class from THREE.PerspectiveCamera and would like to add the ability to make the camera move around on the x,z axes, in the browser I get the position of the the from update_position but the camera does not seem to move
class FPS extends THREE.PerspectiveCamera
{
constructor(params)
{
super(params)
this.keys = {
forward: false,
backward: false,
left: false,
right: false,
}
window.addEventListener('keydown', (event)=>
{
console.info(this.keys);
switch (event.keyCode)
{
case 87: // w
this.keys.forward = true;
break;
case 65: // a
this.keys.left = true;
break;
case 83: // s
this.keys.backward = true;
break;
case 68: // d
this.keys.right = true;
break;
}
this.update_position();
});
window.addEventListener('keyup', (event)=>
{
switch (event.keyCode)
{
case 87: // w
this.keys.forward = false;
break;
case 65: // a
this.keys.left = false;
break;
case 83: // s
this.keys.backward = false;
break;
case 68: // d
this.keys.right = false;
break;
}
});
}
update_position()
{
// x axis moves right or left
if (this.keys.right == true)
{
this.position.x += 1;
}
else if (this.keys.left == true)
{
this.position.x -= 1;
}
// z axis moves forward or backwards
if (this.keys.forward == true)
{
this.position.z += 1;
}
else if (this.keys.backward == true)
{
this.position.z -= 1;
}
console.log(this.position.x);
console.log(this.position.y);
console.log(this.position.z);
}
}
class Game
{
constructor()
{
this.scene = new THREE.Scene();
this.camera = new FPS(100, window.Width/window.Height, 0.1, 1000);
render_scene()
{
requestAnimationFrame(() =>
{
this.renderer.render(this.scene , this.camera);
this.render_scene();
});
}
}
if I replace position with rotation then the camera does rotate but it does not work for the position
Your code seems to work as expected:
let camera, scene, renderer, mesh;
function init() {
camera = new FPS(70, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.z = 10;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
//
class FPS extends THREE.PerspectiveCamera {
constructor(fov, aspect, near, far) {
super(fov, aspect, near, far)
this.keys = {
forward: false,
backward: false,
left: false,
right: false,
}
window.addEventListener('keydown', (event) => {
//console.info(this.keys);
switch (event.keyCode) {
case 87: // w
this.keys.forward = true;
break;
case 65: // a
this.keys.left = true;
break;
case 83: // s
this.keys.backward = true;
break;
case 68: // d
this.keys.right = true;
break;
}
this.update_position();
});
window.addEventListener('keyup', (event) => {
switch (event.keyCode) {
case 87: // w
this.keys.forward = false;
break;
case 65: // a
this.keys.left = false;
break;
case 83: // s
this.keys.backward = false;
break;
case 68: // d
this.keys.right = false;
break;
}
});
}
update_position() {
// x axis moves right or left
if (this.keys.right == true) {
this.position.x += 1;
} else if (this.keys.left == true) {
this.position.x -= 1;
}
// z axis moves forward or backwards
if (this.keys.forward == true) {
this.position.z += 1;
} else if (this.keys.backward == true) {
this.position.z -= 1;
}
//console.log(this.position.x);
//console.log(this.position.y);
//console.log(this.position.z);
}
}
init();
animate();
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.145/build/three.min.js"></script>
The only thing I have updated in FPS was the constructor since the arguments were not applied correctly. Better to explicitly list the parameters.

how to make labels curved in amcharts radar chart

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

Camera Autorotate threejs

How can I make camera to autorotate when i hit any obstacle in threejs. I referred the following link
http://threejs.live/#/webgl_raymarching_reflect
where the rendering restarts when it hits any obstacle. I tried implementing in my project but that doesn't works. How can i implement that in my project?
My map.ts code is
private renderer: THREE.WebGLRenderer;
private camera: THREE.PerspectiveCamera;
public scene: THREE.Scene;
public fieldOfView: number = 10;
public nearClippingPane: number = 1;
public farClippingPane: number = 1000;
public controls: THREE.OrbitControls;
#ViewChild('canvas')
private canvasRef: ElementRef;
constructor(public loadingCtrl: LoadingController) {
this.render = this.render.bind(this);
this.onModelLoadingCompleted = this.onModelLoadingCompleted.bind(this);
}
private get canvas(): HTMLCanvasElement {
return this.canvasRef.nativeElement;
}
private createScene() {
this.scene = new THREE.Scene();
var loader = new THREE.ColladaLoader();
loader.load('assets/Buildings/Block.DAE', this.onModelLoadingCompleted);
}
private onModelLoadingCompleted(collada) {
const loading = this.loadingCtrl.create({
content:'Loading Please Wait...'
});
loading.present();
var modelScene = collada.scene;
modelScene.rotation.x = -0.01 * Math.PI;
// modelScene.rotation.z = 0.03 * Math.PI;
this.scene.add(modelScene);
loading.dismiss();
this.render();
}
private createCamera() {
let aspectRatio = this.getAspectRatio();
this.camera = new THREE.PerspectiveCamera(
this.fieldOfView,
aspectRatio,
this.nearClippingPane,
this.farClippingPane
);
// Set position and look at
this.camera.position.x = 1;
this.camera.position.y = 0.4;
this.camera.position.z = 16;
}
private createLight(){
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
this.scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 1, 1, 0 ).normalize();
this.scene.add( directionalLight );
}
private getAspectRatio(): number {
let height = this.canvas.clientHeight;
if (height === 0) {
return 0;
}
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
return this.canvas.clientWidth / this.canvas.clientHeight;
}
private startRendering() {
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
antialias: true
});
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.renderer.setClearColor(0xffffff, 1);
this.renderer.autoClear = true;
let component: MapComponent = this;
(function render() {
requestAnimationFrame(render);
component.render();
}());
}
public render() {
this.renderer.render(this.scene, this.camera);
}
public addControls() {
this.controls = new THREE.OrbitControls(this.camera);
this.controls.rotateSpeed = 1.0;
this.controls.zoomSpeed = 1.2;
this.controls.addEventListener('change', this.render);
}
/* EVENTS */
public onMouseDown(event: MouseEvent) {
console.log("onMouseDown");
event.preventDefault();
// Example of mesh selection/pick:
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
mouse.x = (event.clientX / this.renderer.domElement.clientWidth) * 2 - 1;
mouse.y = - (event.clientY / this.renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
var obj: THREE.Object3D[] = [];
this.findAllObjects(obj, this.scene);
var intersects = raycaster.intersectObjects(obj);
console.log("Scene has " + obj.length + " objects");
console.log(intersects.length + " intersected objects found")
intersects.forEach((i) => {
console.log(i.object); // do what you want to do with object
});
}
private findAllObjects(pred: THREE.Object3D[], parent: THREE.Object3D) {
// NOTE: Better to keep separate array of selected objects
if (parent.children.length > 0) {
parent.children.forEach((i) => {
pred.push(i);
this.findAllObjects(pred, i);
});
}
}
public onMouseUp(event: MouseEvent) {
console.log("onMouseUp");
}
#HostListener('window:resize', ['$event'])
public onResize(event: Event) {
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
console.log("onResize: " + this.canvas.clientWidth + ", " + this.canvas.clientHeight);
this.camera.aspect = this.getAspectRatio();
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.render();
}
#HostListener('document:keypress', ['$event'])
public onKeyPress(event: KeyboardEvent) {
console.log("onKeyPress: " + event.key);
}
/* LIFECYCLE */
ngAfterViewInit() {
this.createScene();
this.createCamera();
this.createLight();
this.startRendering();
this.addControls();
}
And map.html is
<canvas #canvas (mousedown)="onMouseDown($event)" (mouseup)="onMouseUp($event)"></canvas>
Use collision detection from three js utilities
Also use reference from this stack thread
https://stackoverflow.com/a/11480717/16768028

Make a draggable, rotating wheel snap to evenly distributed positions

I'm rendering a wheel in a WebGL canvas using mrdoob's THREE.js.
I want the wheel to
Spin around it's center
Be draggable by mouse or touch interaction
Slow down by applying fake friction
Snap to the center of a wedge whenever the rotation speed reaches a certain threshold.
You may think of the behaviour of the wheel as that of a lottery wheel.
So far I have achieved points 1-3. This is my code:
'use strict';
var WIDTH = 1080,
HEIGHT = 1080;
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
scene.add(camera);
camera.position.z = 300;
// Create renderer
var container = document.querySelector('#test');
var renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0x000000, 0);
container.appendChild(renderer.domElement);
// Create objects
var wheelMaterial = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('wheel.png'),
depthWrite: false,
alphaTest: 0.5
});
wheelMaterial.overdraw = true;
var wheel = new THREE.Mesh(
new THREE.PlaneGeometry(240, 240),
wheelMaterial);
scene.add(wheel);
// Mouse interaction
var isDragging = false;
var lastMouseCoords = null;
var mouseCoords = null;
container.addEventListener('mousedown', onDragStart, false);
container.addEventListener('touchstart', onDragStart, false);
container.addEventListener('mouseup', onDragEnd, false);
container.addEventListener('mouseout', onDragEnd, false);
container.addEventListener('touchend', onDragEnd, false);
container.addEventListener('mousemove', onMouseMove, false);
container.addEventListener('touchmove', onMouseMove, false);
function onDragStart(e) {
isDragging = true;
console.log('Dragging', e);
mouseCoords = pageCoordsToCanvasCoords(e);
rotationHistory = [];
}
function onDragEnd(e) {
isDragging = false;
lastMouseCoords = null;
mouseCoords = null;
console.log('Drag end');
}
function onMouseMove(e) {
e.preventDefault();
mouseCoords = pageCoordsToCanvasCoords(e);
}
// Utility functions
function pageCoordsToCanvasCoords(e) {
var canvasX;
var canvasY;
if ('touches' in e && e.touches.length > 0) {
canvasX = e.touches[0].pageX;
canvasY = e.touches[0].pageY;
} else {
canvasX = e.pageX
canvasY = e.pageY
}
canvasX -= e.target.offsetLeft;
canvasY -= e.target.offsetTop;
console.log(canvasX, canvasY);
return {
x: canvasX,
y: canvasY
};
}
function mouseCoordsToRotation(x, y) {
var origoX = WIDTH / 2.0,
origoY = HEIGHT / 2.0;
x = x - origoX;
y = y - origoY;
var atan = Math.atan2(x, y);
return atan;
}
function getMeanVelocity(history) {
if (history.length <= 1) {
return 0;
}
var movements = [];
var startTime = history[0].time;
var totalTimeElapsed = 0;
// Start from the second item in deltaRadians
for (var i = 1; i < history.length; i++) {
var item = history[i];
var movement = item.deltaRad;
movements.push(item.deltaRad);
var movementTimeDelta = item.time - startTime - totalTimeElapsed;
if (movementTimeDelta < 0) {
console.error('movementTimeDelta for history entry #' +
i + ' has travelled back in time somehow.');
}
totalTimeElapsed += movementTimeDelta;
}
var sum = movements.reduce(function (a, b) {
return a + b;
});
return sum / totalTimeElapsed;
}
function applyFakeFriction(velocity, time) {
/*
var currentRotation = wheel.rotation.z;
var nearestBorder = 0;
var nearestBorderDistance = 100;
for (var i = 0; i < PARTITIONS; i++) {
var partition = PARTITION_ARC * i - PARTITION_ARC * PARTITIONS / 2;
var distance = currentRotation - partition;
if (distance < 0) {
distance /= -1;
}
if (distance < nearestBorderDistance) {
console.log('distance is less than nearestBorderDistance')
nearestBorder = partition;
nearestBorderDistance = distance;
if (nearestBorderDistance < 0) {
nearestBorderDistance /= -1;
}
}
}
console.log('nearestBorderDistance: ', nearestBorderDistance);
*/
for (var i = 0; i < time; i++) {
velocity -= WHEEL_FRICTION; // * (nearestBorderDistance * BORDER_FRICTION);
}
return velocity;
}
var rotation = 1;
function snap() {
isSnapping = true;
/* Disabled, this the issue I'm asking about in the post
var update = function () {
cube.position.rotation = current.rotation;
}
var current = {
rotation: rotation
};
TWEEN.removeAll();
var easing = TWEEN.Easing['Elastic']['EaseInOut'];
var tweenHead = neww TWEEN.Tween(current)
.to({rotation: rotation})
.easing(easing)
.onUpdate(update);
tweenHead.start();
*/
}
var rotationHistory = []
var ROTATION_HISTORY_MAX_LENGTH = 5;
var WHEEL_FRICTION = 0.000001;
var BORDER_FRICTION = 2;
var PARTITIONS = 12;
var PARTITION_ARC = 1 * Math.PI / (PARTITIONS / 2); // The width of each section
var wheelVelocity = 0.1;
var wheelSlowDownVelocity = 0;
var lastWheelRotationTime;
var isSnapping = false;
// Render
function tick() {
// Rotate wheel
var currentTime = (new Date).getTime();
if (lastMouseCoords && isDragging) {
// Reset the velocity for the slowdown
wheelSlowDownVelocity = 0;
// Get the delta rotation since last mouse coordinates
var deltaRadians = mouseCoordsToRotation(mouseCoords.x, mouseCoords.y)
- mouseCoordsToRotation(lastMouseCoords.x, lastMouseCoords.y);
// Set the wheel rotation
wheel.rotation.z += deltaRadians;
// Save the rotation in the history and remove any excessive elements
rotationHistory.push({
time: currentTime,
deltaRad: deltaRadians
});
while (rotationHistory.length > ROTATION_HISTORY_MAX_LENGTH) {
rotationHistory.shift();
}
}
if (isDragging) {
lastMouseCoords = mouseCoords;
}
// Continue rotation of the released wheel
if (!isDragging && !lastMouseCoords && lastWheelRotationTime) {
var delta = currentTime - lastWheelRotationTime;
if (wheelSlowDownVelocity == 0) {
var meanVelocityOverTime = getMeanVelocity(rotationHistory);
wheelSlowDownVelocity = meanVelocityOverTime;
} else {
var currentIsNegative = wheelSlowDownVelocity < 0 ? true : false;
var currentVelocity = wheelSlowDownVelocity;
if (currentIsNegative) {
currentVelocity /= -1;
}
console.log('Current velocity: ', currentVelocity);
console.log('delta: ', delta);
var newVelocity = applyFakeFriction(currentVelocity,
delta);
console.log('New velocity: ', newVelocity);
if (newVelocity < 0) {
wheelSlowDownVelocity = 0;
rotationHistory = [];
} else {
if (currentIsNegative) {
// Revert to old polarity
newVelocity /= -1;
}
wheelSlowDownVelocity = newVelocity;
}
}
wheel.rotation.z += wheelSlowDownVelocity * delta;
}
while (wheel.rotation.z > 2 * Math.PI) {
console.log('Correcting rotation: ', wheel.rotation.z);
wheel.rotation.z -= 2 * Math.PI;
}
while (wheel.rotation.z < - (2 * Math.PI)) {
console.log('Correcting rotation: ', wheel.rotation.z);
wheel.rotation.z += 2 * Math.PI;
}
// Update the history record
lastWheelRotationTime = currentTime;
// Render scene and attach render callback to next animation frame.
renderer.render(scene, camera);
window.requestAnimationFrame(tick);
}
tick();
I have the complete code, minus wheel.png over at https://gist.github.com/joar/5747498.
I have been searching for examples of this behaviour but this far I haven't found any.
Note to editors. Please do not change the tags of this post. tween.js != TweenJS.
I have solved the issue.
'use strict';
function Wheel (element, options) {
var self = this;
// Variable initialization
var WIDTH = options.width;
var HEIGHT = options.height;
if (!options.image) {
throw new Error('Image argument missing');
}
var image = options.image;
var showStats = options.showStats || options.stats;
// Core variables
var stats;
var wheel;
var domElement;
var scene;
var camera;
var renderer;
var rotationHistory;
var input;
var animate;
var run = false;
var ROTATION_HISTORY_MAX_LENGTH = 5;
switch (typeof element) {
case 'string':
domElement = document.querySelector(element);
break;
default:
if ('className' in element) {
domElement = element;
} else {
throw new Error('Invalid element: ', element);
}
}
if (typeof element == 'undefined') {
throw new Error('Invalid element.')
}
/* Initializes the WebGL canvas with the wheel plane */
function setupScene() {
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
scene = new THREE.Scene();
scene.add(camera);
camera.position.z = 300;
// Create renderer
var container = domElement;
renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH * 2, HEIGHT * 2);
renderer.setClearColor(0x000000, 0);
// Create objects
var wheelMaterial = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture(image),
depthWrite: false,
alphaTest: 0.5
});
wheelMaterial.overdraw = true;
wheel = new THREE.Mesh(
new THREE.PlaneGeometry(245, 245),
wheelMaterial);
scene.add(wheel);
container.appendChild(renderer.domElement);
}
function setupStats() {
// Init stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
}
function setup() {
setupScene();
if (showStats) {
setupStats();
}
}
setup();
// The tick function
function update() {
animate.update(); // Process interactions
self.renderer.render(self.scene, self.camera);
if (showStats) {
self.stats.update();
}
if (run) {
window.requestAnimationFrame(update);
}
}
animate = new Animate();
// Start and run the wheel every animationframe
function start() {
self.input = input = new Input(); // Start capturing input
run = true;
update();
}
/**
* Animate the wheel
*/
function Animate() {
var self = this;
self.velocity = 0;
var velocityPositive = 0;
self.friction = 0.001;
self.snapThreshold = 0.03;
self.isSnapping = false;
var lastAnimationTime;
self.tween;
var rotationHistory = [];
var PARTITIONS = 12;
var PARTITION_ARC = 1 * Math.PI / (PARTITIONS / 2); // The width of each section
function update() {
var currentTime = (new Date).getTime();
velocityPositive = self.velocity;
if (velocityPositive < 0) {
velocityPositive /= -1;
}
if (!self.isSnapping
&& !input.isDragging
&& velocityPositive < self.snapThreshold
&& velocityPositive > 0
&& lastAnimationTime) {
rotationHistory = [];
snap();
}
if (input.isDragging) {
self.isSnapping = false;
TWEEN.removeAll();
}
if (!self.isSnapping) {
/**
* If the mouse is dragging the wheel
*/
if (input.lastMouseCoords && input.isDragging && !input.isSnapping) {
// Reset the velocity for the slowdown
self.velocity = 0;
// Get the delta rotation since last mouse coordinates
var deltaRadians = input.mouseCoordsToRadian(
input.mouseCoords.x, input.mouseCoords.y)
- input.mouseCoordsToRadian(
input.lastMouseCoords.x,
input.lastMouseCoords.y);
// Set the wheel rotation
wheel.rotation.z += deltaRadians;
// Save the rotation in the history and remove any excessive elements
rotationHistory.push({
time: currentTime,
deltaRad: deltaRadians
});
while (rotationHistory.length > ROTATION_HISTORY_MAX_LENGTH) {
rotationHistory.shift();
}
}
if (input.isDragging) {
input.lastMouseCoords = input.mouseCoords;
}
// Continue rotation of the released wheel
if (!input.isDragging
&& !input.lastMouseCoords
&& lastAnimationTime
&& !self.isSnapping) {
var delta = currentTime - lastAnimationTime;
if (self.velocity == 0) {
var meanVelocityOverTime = getMeanVelocity(rotationHistory);
self.velocity = meanVelocityOverTime;
} else if (!self.isSnapping && !self.isDragging) {
var currentIsNegative = self.velocity < 0 ? true : false;
var currentVelocity = self.velocity;
if (currentIsNegative) {
currentVelocity /= -1;
}
var newVelocity = applyFakeFriction(currentVelocity,
delta);
if (newVelocity < 0) {
self.velocity = 0;
rotationHistory = [];
} else {
if (currentIsNegative) {
// Revert to old polarity
newVelocity /= -1;
}
self.velocity = newVelocity;
}
}
wheel.rotation.z += self.velocity * delta;
}
if (!self.isSnapping) {
while (wheel.rotation.z > 2 * Math.PI) {
wheel.rotation.z -= 2 * Math.PI;
}
while (wheel.rotation.z < - (2 * Math.PI)) {
wheel.rotation.z += 2 * Math.PI;
}
}
}
// Update snap tween
TWEEN.update();
// Update the history record
lastAnimationTime = currentTime;
}
function applyFakeFriction(velocity, time) {
/*
var currentRotation = wheel.rotation.z;
var nearestBorder = 0;
var nearestBorderDistance = 100;
for (var i = 0; i < PARTITIONS; i++) {
var partition = PARTITION_ARC * i - PARTITION_ARC * PARTITIONS / 2;
var distance = currentRotation - partition;
if (distance < 0) {
distance /= -1;
}
if (distance < nearestBorderDistance) {
console.log('distance is less than nearestBorderDistance')
nearestBorder = partition;
nearestBorderDistance = distance;
if (nearestBorderDistance < 0) {
nearestBorderDistance /= -1;
}
}
}
console.log('nearestBorderDistance: ', nearestBorderDistance);
*/
for (var i = 0; i < time; i++) {
velocity -= self.friction; // * (10000 * wheelSlowDownVelocityPositive); // * (nearestBorderDistance * BORDER_FRICTION);
}
return velocity;
}
function getNearestWedge() {
var currentRotation = wheel.rotation.z;
var nearestBorder = 0;
var nearestBorderDistance = 100;
for (var i = 0; i < PARTITIONS; i++) {
var partition = PARTITION_ARC * i - PARTITION_ARC * PARTITIONS / 2;
var distance = currentRotation - partition;
if (distance < 0) {
distance /= -1;
}
if (distance < nearestBorderDistance) {
console.log('distance is less than nearestBorderDistance')
nearestBorder = partition;
nearestBorderDistance = distance;
if (nearestBorderDistance < 0) {
nearestBorderDistance /= -1;
}
}
}
return {
position: nearestBorder,
distance: nearestBorderDistance
};
}
function snap() {
console.log('Snapping');
if (self.isSnapping) {
console.error('Already snapping, aborting.');
return;
}
self.isSnapping = true;
self.velocity = 0;
var nearest = getNearestWedge();
TWEEN.removeAll();
console.log('nearest: ', nearest.position, nearest.distance)
self.tween = new TWEEN.Tween({r: wheel.rotation.z})
.to({r: nearest.position})
.easing(TWEEN.Easing.Elastic.Out)
.onUpdate(onUpdate)
.onComplete(onComplete)
.start();
function onUpdate() {
//console.log('current: ', this.r, self.velocity);
wheel.rotation.z = this.r;
};
function onComplete() {
self.isSnapping = false;
console.log('Not snapping');;
}
}
function getMeanVelocity(history) {
if (history.length <= 1) {
return 0;
}
var movements = [];
var startTime = history[0].time;
var totalTimeElapsed = 0;
// Start from the second item in deltaRadians
for (var i = 1; i < history.length; i++) {
var item = history[i];
var movement = item.deltaRad;
movements.push(item.deltaRad);
var movementTimeDelta = item.time - startTime - totalTimeElapsed;
if (movementTimeDelta < 0) {
console.error('movementTimeDelta for history entry #' +
i + ' has travelled back in time somehow.');
}
totalTimeElapsed += movementTimeDelta;
}
var sum = movements.reduce(function (a, b) {
return a + b;
});
return sum / totalTimeElapsed;
}
// Internal utilities
function log() {
if (console && _log) {
var args = Array.prototype.slice.call(arguments, 0);
args.unshift('Animate: ')
console.log.apply(console, args);
}
}
// exports
this.update = update;
this.rotationHistory = rotationHistory;
this.PARTITIONS = PARTITIONS;
this.PARTITION_ARC = PARTITION_ARC;
this.snap = snap;
return this;
}
/**
* Handles input to the wheel.
*/
function Input() {
var self = this;
var _log = true;
domElement.addEventListener('mousedown', onDragStart, false);
//domElement.addEventListener('touchstart', onDragStart, false);
domElement.addEventListener('mouseup', onDragEnd, false);
domElement.addEventListener('mouseout', onDragEnd, false);
//domElement.addEventListener('touchend', onDragEnd, false);
domElement.addEventListener('mousemove', onMouseMove, false);
//domElement.addEventListener('touchmove', onMouseMove, false);
function onDragStart(e) {
self.isDragging = true;
log('Drag start');
self.mouseCoords = pageCoordsToCanvasCoords(e);
animate.rotationHistory = [];
}
function onDragEnd(e) {
self.isDragging = false;
self.lastMouseCoords = null;
self.mouseCoords = null;
log('Drag end');
}
function onMouseMove(e) {
e.preventDefault();
self.mouseCoords = pageCoordsToCanvasCoords(e);
}
function pageCoordsToCanvasCoords(e) {
var canvasX, canvasY;
if ('touches' in e && e.touches.length > 0) {
canvasX = e.touches[0].pageX;
canvasY = e.touches[0].pageY;
} else {
canvasX = e.pageX
canvasY = e.pageY
}
canvasX -= e.target.offsetLeft;
canvasY -= e.target.offsetTop;
// console.log(canvasX, canvasY);
return {
x: canvasX,
y: canvasY
};
}
function mouseCoordsToRadian(x, y) {
var origoX = WIDTH / 2.0,
origoY = HEIGHT / 2.0;
x = x - origoX;
y = y - origoY;
var atan = Math.atan2(x, y);
return atan;
}
// exports
this.mouseCoordsToRadian = mouseCoordsToRadian;
function log() {
if (console && _log) {
var args = Array.prototype.slice.call(arguments, 0);
args.unshift('Input: ')
console.log.apply(console, args);
}
}
return this;
}
// Internal utils
function log() {
if (console && _log) {
var args = Array.prototype.slice.call(arguments, 0);
args.unshift('Wheel: ')
console.log.apply(console, args);
}
}
// exports
self.start = start;
self.update = update;
self.scene = scene;
self.camera = camera;
self.wheel = wheel;
self.renderer = renderer;
self.stats = stats;
self.domElement = domElement;
self.input = input;
self.animate = animate;
return self;
}

Excanvas does not work in IE8

Excanvas does not work in IE8!!! I write program to paint by mouse on canvas element. There are fragment of my js-code
window.attachEvent('onload', function () {
function init() {
var w = document.getElementById('signatureImage').getAttribute('width');
var h = document.getElementById('signatureImage').getAttribute('height');
var removeSignatureImage = document.getElementById('signatureImage');
removeSignatureImage.parentNode.removeChild(removeSignatureImage);
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
canvas.setAttribute('style', 'border:1px solid #000000');
canvas.setAttribute('id', 'signatureImage');
canvasDiv.appendChild(canvas);
if (typeof G_vmlCanvasManager != 'undefined') {
canvas = window.G_vmlCanvasManager.initElement(canvas);
}
context = canvas.getContext("2d");
tool = new tool_pencil();
// Attach the mousedown, mousemove and mouseup event listeners.
var trackend = false;
var trackstart = false;
var trackmid = false;
canvas.onselectstart = function () {
canvas.onmousemove(); trackstart = true;
return false; }
canvas.onclick = function () { trackend = true; }
canvas.onmousemove = function () {
var mtarget = document.getElementById('signatureImage');
var x = event.clientX - canvas.offsetLeft;
var y = event.clientY - canvas.offsetTop;
var mtype = 'mousemove';
if (trackstart) {
trackstart = false;
trackmid = true;
mtype = 'mousedown';
}
if (trackend) {
trackmid = false;
mtype = 'mouseup';
}
if (trackend || trackmid || trackstart) {
trackend = false;
ev_canvas({
type: mtype,
_x: x,
_y: y,
target: mtarget
});
}
}
}
function tool_pencil() {
var tool = this;
this.started = false;
function getCoord(ev) {
var x = ev._x;
var y = ev._y;
if (tool.started == true) {
coords += x + "," + y + " ";
}
return [x, y];
}
this.mousedown = function (ev) {
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
this.mousemove = function (ev) {
if (tool.started) {
context.lineTo(ev._x, ev._y);
context.stroke();
var coord = getCoord(ev);
}
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
coordList += coords + ";";
document.getElementById('coord').value = coordList;
coords = "";
}
};
}
When there is context.lineTo(ev._x, ev._y);
context.stroke(); - nothing happens! Although the coordinates are passed and canvas painted and initialized

Resources