Trying to do slow scrolling, but it seems gsap can't handle as many events per scroll - vue.js

I need to slow down scroll speed on the page to animate elements better (For example one wheel event on mine laptop makes deltaY = 378 and it's too hard to calculate correct offset to start animations). I decided to disable scroll with e.preventDefault() and e.returnValue = false. It works well, but sometimes page starts 'jumping', when u try to scroll.
import { gsap } from 'gsap'
import { ScrollToPlugin } from 'gsap/src/ScrollToPlugin.js'
gsap.registerPlugin(ScrollToPlugin);
export default {
data: () => {
return {
currentSlide: 0,
offsetTop: 0,
pageHeight: 0,
wheelCounter: 0,
scrollCounter: 0,
slides: [
{
id: 'ad1',
bg: '/hall.jpg'
},
{
id: 'ad2',
bg: '/home.jpg'
},
{
id: 'ad3',
bg: '/hall.jpg'
},
{
id: 'ad4',
bg: '/home.jpg'
}]
}
},
methods: {
checkScroll (event) {
event.returnValue = false
event.preventDefault()
let sliderGap = 300
let current, next
let tl = gsap.timeline()
this.wheelCounter += parseInt(event.deltaY / 5)
if (this.wheelCounter < 0) this.wheelCounter = 0
gsap.to(window, {scrollTo: this.wheelCounter, duration: 0.2})
current = parseInt(this.wheelCounter / sliderGap)
if (current > 4) current = 4
if ((current != this.currentSlide) && (current < 4)) {
document.getElementById('main').style.backgroundImage = 'url("' + this.slides[current].bg + '")'
tl.to('#' + this.slides[this.currentSlide].id, {x: 20, opacity: 0, duration: 0.3})
tl.to('#' + this.slides[current].id, {x: -20, opacity: 1, duration: 0.7})
this.currentSlide = current
}
if (window.scrollY > 300) {
tl.to('#about_header', {x: 0, opacity: 1, duration: 0.7})
tl.to('#about_description', {y: 0, opacity: 1, duration: 0.7}, 0.5)
tl.to('#about_picture', {x: 0, opacity: 1, duration: 1}, 0.5)
}
if (window.scrollY > 500) {
tl.to('#left_offer', {y: 0, opacity: 1, duration: 1}, 0)
tl.to('#right_offer', {y: 0, opacity: 1, duration: 1}, 0.5)
tl.to('#offers_description', {x: 0, opacity: 1, duration: 0.5}, 1.5)
}
}
}
}
I thought about adding vue-observe-visibility package and perform animation via it. But scroll should be smooth too and idk how can I do it.

Related

threeJS Raycaster.set() not detecting intersections ( plane )

const origin = new THREE.Vector3(...point, -100),
direction = new THREE.Vector3(0, 0, 1) // is a normalized vector
const raycaster = new THREE.Raycaster( origin, direction );
const intersects = raycaster.intersectObject( dem ); // is a planeGeometry (mesh)
const length = 2000;
const hex = 0xff0000;
const arrowHelper = new THREE.ArrowHelper( direction, origin, length, hex );
cx3d.addObject( arrowHelper );
if( intersects.length ){
console.log( intersects[0] )
}
now intersects = [], but point is in the plane mesh, so I need help, thank everyone
like this https://jsfiddle.net/Hoshua/obm8ke0q/2/
You need to update your mesh matrix world with mesh.updateMatrixWorld();. See below.
function seta(){
const origin = new THREE.Vector3(0.5, 0, 0),
direction = new THREE.Vector3(-1, 0, 0)
const raycaster = new THREE.Raycaster( origin, direction );
mesh.updateMatrixWorld(); // here
const intersects = raycaster.intersectObject( mesh );
const length = 1.5;
const hex = 0xff0000;
const arrowHelper = new THREE.ArrowHelper( direction, origin, length, hex );
scene.add( arrowHelper );
console.log(intersects)
}
Not sure if link will work. In case: https://jsfiddle.net/4n0tgwuo/
Output:
[{
distance: 0.5,
face: {
a: 0,
b: 2,
c: 1,
materialIndex: 0,
normal: { ... }
},
faceIndex: 0,
object: {
animations: [],
castShadow: false,
children: [],
frustumCulled: true,
geometry: { ... },
isMesh: true,
isObject3D: true,
layers: { ... },
material: { ... },
matrix: { ... },
matrixAutoUpdate: true,
matrixWorld: { ... },
matrixWorldNeedsUpdate: false,
name: "",
parent: { ... },
position: { ... },
quaternion: { ... },
receiveShadow: false,
renderOrder: 0,
rotation: { ... },
scale: { ... },
type: "Mesh",
up: { ... },
userData: { ... },
uuid: "cb14eb31-b325-4252-8fb6-0d4417cbf39d",
visible: true
},
point: {
isVector3: true,
x: 0,
y: 0,
z: 0
},
uv: {
isVector2: true,
x: 0.5,
y: 0.5
}
}, {
distance: 0.5,
face: {
a: 2,
b: 3,
c: 1,
materialIndex: 0,
normal: { ... }
},
faceIndex: 1,
object: [circular object Object],
point: {
isVector3: true,
x: 0,
y: 0,
z: 0
},
uv: {
isVector2: true,
x: 0.5,
y: 0.5
}
}]

On-click event display data on heap map in highcharts

This image contains details about the number of projects was uploaded by the particular user
I am using heapmap highchart to display project details of a user.
on Y-axis => represents week of the days which ranges from 0 to 6
eg. Mon = 0, Tue= 1,....Sun=6
on X-axis => represents months, which ranges from 0 to 11
eg. Jan = 0, Feb = 1, ... Dec = 11
Data format
X Y Data
[0 ,1 , 3]
Suppose, 3 projects was uploaded by a user on monday in the month of January.
When I click on that 3 on heap map then it should display a pop box,
which should include project name,date and time
eg. Project Name : image recognition
Date : Uploaded on Jan 4,2019
Time : 10:04:00
In this I have hardcoded the data.
https://jsfiddle.net/k9hyfjmL/
This code retrieve data from mysql database and populates on heap map, which indicates number of projects was uploaded by a user.
$(document).on('click', '.click_once', function()
{
$.ajax(
{
url: '/profile/heap_map_data',
type: 'GET',
success: function(response)
{
var chart_data = [];
var skip_1st_data = 1;
var take_Data_upto = 0;
for (var i = 0, len = response.length; i < len; i++)
{ if(skip_1st_data == 1)
{
skip_1st_data = 2;
}
else{
take_Data_upto = take_Data_upto + 1;
chart_data.push(response[i]);
if(take_Data_upto == 31)
{
break;
}
}
}
console.log(chart_data)
Highcharts.chart('heap_map_chart',
{
chart:
{
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1,
},
title:
{
text: 'Project Details'
},
xAxis:
{
categories: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
},
yAxis:
{
categories: ['Mon','Tue','Wed','Thur','Fri','Sat','Sun'],
title: null
},
colorAxis:
{
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend:
{
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip:
{
formatter: function ()
{
return + this.point.value + ' <b> project was uploaded on ' + this.series.xAxis.categories[this.point.x] + ' date, 2019' + '<br /> click to view more' ;
}
},
series: [
{
borderWidth: 1,
data: chart_data,
dataLabels:
{
enabled: true,
color: '#000000'
}
}]
});
},
error : function(jqXHR, textStatus, errorThrown)
{
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
alert(errorThrown);
}
});
});
You can use point.events.click function to display some more information in another HTML element:
series: [{
point: {
events: {
click: function() {
document.getElementById('moreInfo').innerText =
'value: ' + this.value;
}
}
},
...
}]
Live demo: https://jsfiddle.net/BlackLabel/p261zg9d/
API Reference: https://api.highcharts.com/highcharts/series.heatmap.point.events.click

Vue Chart.js - simple dot/line on bar chart

I'd need to add a simple dot/vertical line on my bar chart that has a dynamical X value, and 0 for Y value. Preview of what I need (the red dot):
Where the green values are dynamic.
Preview of my current state:
Where 3.30 should be the X coordinate of the dot - [3.30, 0].
I'm using Vue chart for the charts and I tried do create a mixed one with the bar and scatter but scatter requires type: 'linear' for it's xAxis which doesn't suit my need for the bar chart.
So I tried with chartjs-plugin-annotation and it's box type which accepts "coordinates" but the problem here is that the X value must be a fixed value on the X axis (labels object). If I put for the X axis [3,0] it will work, but if there is a decimal number, like [3.5, 0], it won't work.
// data
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
min: 0,
max: 1,
stepSize: 0.1
}
}]
}
}
// computed
labels: [1, 2, 3, 4, 5, 6], // fixed value, there are always 6 bars
datasets: [
{
label: 'Values',
backgroundColor: '#f89098',
data: this.tableInputValues // array of decimal values
}
]
So, my question is how to put a "simple" dot, or a vertical line, on a Chart.js bar chart where the dot has a dynamical value for the X axis -> [dynamic value, 0].
FYI - it's about Expected value
As far as I understand Vue Chart works using canvas (as seen on Demo page).
So, my suggestion here is to retrieve the canvas node representing the chart in your DOM and dynamically write the desired dot. For example:
var c = document.getElementById("bar-chart"); //hereby assuming canvas named "bar-chart"
var ctx = c.getContext("2d");
ctx.fillStyle = "#ff0000"; //red color for the dot
ctx.beginPath();
let yPosition = c.height - 5; //fixed y position
let xPosition = 35; //that's the dynamic expected value
ctx.arc(xPosition, yPosition, 2.5, 0, 2 * Math.PI);
ctx.fill();
Here you find a demo showing how to achieve that using Vue. In this scenario, you need to wrap the code to draw a dot on the canvas in a afterDraw hook. This hook needs to be attached to the chart component as a plugin, so like this:
...
mounted () {
//adding the plugin to draw the red dot
this.addPlugin({
id: 'chart-plugin',
afterDraw: function (chart) {
var c = chart.canvas;
var ctx = c.getContext("2d");
ctx.fillStyle = "#ff0000";
ctx.beginPath();
let xPosition = 742; //x positioning to be calculated according to your needs
let yPosition = c.height - 28;
ctx.arc(xPosition, yPosition, 3, 0, 2 * Math.PI);
ctx.fill();
}
});
//actual chart rendering
this.renderChart({
...
});
}
...
For the sake of completeness, here you find the list of all the available hooks of Chart.js plugin API.
This is my solution for your problem https://jsfiddle.net/huynhsamha/e54djwxp/
And this is screenshot for the result
In my solution, I use type="line" and both x-axis and y-axis with type="linear". I also add property options to <chart> for using options in ChartJS
<div id="vue">
<chart type="line" :data="data" :options="options"></chart>
</div>
The options will set-up x-axis and y-axis to render the data points and expected value:
options: {
scales: {
xAxes: [{
type: 'linear',
ticks: {
min: 1,
max: 6,
stepSize: 1
}
}],
yAxes: [{
type: 'linear',
ticks: {
min: 0,
max: 1,
stepSize: 0.1
}
}]
}
}
And the data will have 2 datasets. The first is data points, use type line, and the second is the expected value which use type bubble.
data: {
datasets: [{
label: 'Frequency Data',
data: dataPoints.map(({ val, freq }) => ({
x: val,
y: freq
})),
backgroundColor: 'rgba(72, 202, 59, 0.4)',
borderColor: 'rgba(72, 202, 59, 1)'
}, {
label: 'Expected Value',
type: 'bubble',
data: [{
x: expectedValue,
y: 0,
r: 8 // radius
}],
backgroundColor: 'rgba(255, 68, 0, 0.4)',
borderColor: 'rgba(255, 68, 0, 1)'
}]
},
In datasets, we have dataPoints and expectedValue, it will be fetched from API to get your data points. I also simulate the simple API for data points:
// simulate the API to get data points
const retrieveData = () => [
{ val: 1, freq: 0.15 },
{ val: 2, freq: 0.25 },
{ val: 3, freq: 0.3 },
{ val: 4, freq: 0.2 },
{ val: 5, freq: 0.1 },
{ val: 6, freq: 0.45 }
]
// fetch your data here, return array of JSON { val, freg }
const dataPoints = retrieveData() || [];
// calculate expected value = sum( val * freq ) each i in dataPoints
const expectedValue = dataPoints.reduce((cur, { val, freq }) => cur + val * freq, 0).toFixed(4);
You can run snippet or run on fiddle https://jsfiddle.net/huynhsamha/e54djwxp/92/
<script async src="//jsfiddle.net/huynhsamha/e54djwxp/92/embed/js,html,css,result/dark/"></script>

Chartist Pie Char Custom Label

I am trying to customize the label of Chartist Pie Chart so that it will show both the label and value.
So in the example below, I would want the label to show "Bananas - 20", "Apples - 15", "Grapes - 40". I know I can just change the labels:, but is there a way to do that with the labelInterpolationFnc?
https://jsfiddle.net/ckmz7L1p/
var data = {
labels: ['Bananas', 'Apples', 'Grapes'],
series: [20, 15, 40]
};
var options = {
labelInterpolationFnc: function(value) {
return value[0]
}
};
var responsiveOptions = [
['screen and (min-width: 640px)', {
chartPadding: 30,
labelOffset: 100,
labelDirection: 'explode',
labelInterpolationFnc: function(value) {
return value;
}
}],
['screen and (min-width: 1024px)', {
labelOffset: 80,
chartPadding: 20
}]
];
new Chartist.Pie('.ct-chart', data, options, responsiveOptions);
Got it figured out. Didn't realize labelInterpolationFnc can take function with both value and index parameters.
var data = {
labels: ['Bananas', 'Apples', 'Grapes'],
series: [20, 15, 40]
};
var options = {
width: "400px",
height: "400px",
labelInterpolationFnc: function(value, idx) {
return value + " - " + data.series[idx];
}
};
var responsiveOptions = [
['screen and (min-width: 640px)', {
chartPadding: 0,
labelOffset: 0,
labelDirection: 'explode',
labelInterpolationFnc: function(value, idx) {
return value + " - " + data.series[idx];
}
}],
['screen and (min-width: 1024px)', {
labelOffset: 30,
chartPadding: 0
}]
];
new Chartist.Pie('.ct-chart', data, options, responsiveOptions);

How to customize czml datasource?

I have a CZML data that I extracted via python.
I have buildings, with their geometry, height, building ID, and intervals. each interval has a value.
After loading the czml data to Cesium, I'd like to access the attributes and then customize the color of the buildings according to the value given.
Here is a sample of my CZML:
[{
"id": "document",
"version": "1.0"
}, {
"id": 32,
"availability": "2014-01-01T00:00:00Z/2014-12-31T00:00:00Z",
"polygon": {
"positions": {
"cartographicDegrees": [54.7162360431897, 24.4519912715277, 0, 54.716219612921, 24.4519754832587, 0, 54.7162501395131, 24.4519488635358, 0, 54.7162465684811, 24.4519454316688, 0, 54.7162670831639, 24.4519275432238, 0, 54.7162707308589, 24.4519310439514, 0, 54.7163022563025, 24.4519035537608, 0, 54.7161962974502, 24.4518018819532, 0, 54.7161647729823, 24.4518293730395, 0, 54.7162035538772, 24.4520196028966, 0, 54.7162360431897, 24.4519912715277, 0]
},
"someProperty": [{
"interval": "2014-00-01T00:00:00Z/2014-01-01T00:00:00Z",
"En_C_need": 0.7
}, {
"interval": "2014-01-01T00:00:00Z/2014-02-01T00:00:00Z",
"En_C_need": 1.0
}, {
"interval": "2014-02-01T00:00:00Z/2014-03-01T00:00:00Z",
"En_C_need": 2.6
}, {
"interval": "2014-03-01T00:00:00Z/2014-04-01T00:00:00Z",
"En_C_need": 12.1
}, {
"interval": "2014-04-01T00:00:00Z/2014-05-01T00:00:00Z",
"En_C_need": 30.2
}, {
"interval": "2014-05-01T00:00:00Z/2014-06-01T00:00:00Z",
"En_C_need": 37.8
}],
"extrudedHeight": 6.0
}
}]
I have other GeoJSON data that I customized, I tried the same method but it didn't work.
Here is what I'm trying to do (this does not work):
var test2 = Cesium.CzmlDataSource.load ('Data/czml/TESTING/example_8.czml');
test2.then(function (dataSource) {
viewer.dataSources.add(test2);
viewer.zoomTo (test2);
var entities = dataSource.entities.values;
var colorHash = {};
var Energy = [];
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
Energy = entity.someProperty.En_C_need;
var color = colorHash [Energy];
if(!color ) {
if (Energy < 5 ) {
color = Cesium.Color.DARKSALMON.withAlpha (0.95);
} else if (Energy < 10) {
color = Cesium.Color.BURLYWOOD.withAlpha (0.95);
} else if (Energy < 20) {
color = Cesium.Color.RED.withAlpha (0.95);
} else {
color = Cesium.Color.PINK.withAlpha (0.95);
};
colorHash[Energy] = color;
};
entity.polygon.fill = true;
entity.polygon.material = color;
entity.polygon.outline = false;
};
});
To start with the solution - here's the working plnkr:
https://plnkr.co/edit/P1Cg4DNJYtK9r9XrLzxK?p=preview
I've changed several things in your code:
1) viewer.dataSources.add(test2); should be outside your promise (it doesn't really matter, but it's cleaner code - using the promise inside the promise feels strange).
2) According to the CZML properties spec, you need to place the properties in the right location in the CZML. It should not be inside the polygon, but in the "root":
var czml = [{"id": "document", "version": "1.0"},
{
"id": 32, "availability": "2014-01-01T00:00:00Z/2014-12-31T00:00:00Z", "properties": {
"someProperty": [
{"interval": "2014-00-01T00:00:00Z/2014-01-01T00:00:00Z", "En_C_need": 0.7},
{"interval": "2014-01-01T00:00:00Z/2014-02-01T00:00:00Z", "En_C_need": 1.0},
{"interval": "2014-02-01T00:00:00Z/2014-03-01T00:00:00Z", "En_C_need": 2.6},
{"interval": "2014-03-01T00:00:00Z/2014-04-01T00:00:00Z", "En_C_need": 12.1},
{"interval": "2014-04-01T00:00:00Z/2014-05-01T00:00:00Z", "En_C_need": 30.2},
{"interval": "2014-05-01T00:00:00Z/2014-06-01T00:00:00Z", "En_C_need": 37.8}
],
},
"polygon": {
"positions": {
"cartographicDegrees":
[54.7162360431897, 24.4519912715277, 0, 54.716219612921, 24.4519754832587, 0, 54.7162501395131, 24.4519488635358, 0, 54.7162465684811, 24.4519454316688, 0, 54.7162670831639, 24.4519275432238, 0, 54.7162707308589, 24.4519310439514, 0, 54.7163022563025, 24.4519035537608, 0, 54.7161962974502, 24.4518018819532, 0, 54.7161647729823, 24.4518293730395, 0, 54.7162035538772, 24.4520196028966, 0, 54.7162360431897, 24.4519912715277, 0]
},
"extrudedHeight": 6.0
}
}];
Then you can ask for the properties according to the interval (Energy = entity.properties.getValue(viewer.clock.currentTime).someProperty.En_C_need;) and get the Energy at viewer's current time.
Update after commentchatting:
Your code was not meant to change dynamically. You need to set the value either by callbackProperty as in this example: plnkr.co/edit/lm290uaQewEvfIOgXbDP?p=preview or by using timeIntervalCollection