SVG animation / TweenMax / Reverse animation - animation

Here is the animation which is running with yoyo = true meaning the animation goes one way and then do the "reverse" animation.
I would like to be able to play the animation in mode reverse without having the yoyo mode.
In other words, I would like to have the second part (the reverse one)
https://codepen.io/chrisgannon/pen/greVXG
var xmlns = "http://www.w3.org/2000/svg",
xlinkns = "http://www.w3.org/1999/xlink",
select = function(s) {
return document.querySelector(s);
},
selectAll = function(s) {
return document.querySelectorAll(s);
}
TweenMax.set('svg', {
visibility: 'visible',
transformOrigin:'50% 50%',
scale:1
})
var mainTl = new TimelineMax({repeat:-1, yoyo:true, repeatDelay:2});
var skySunTl = new TimelineMax({paused:true});
skySunTl.fromTo('#lower', 10, {
stopColor:'#020111'
},{
stopColor:'#CD82A0',
ease:Linear.easeNone
})
.fromTo('#upper', 10, {
stopColor:'#1F1F2B'
},{
stopColor:'#4B4A6A',
ease:Linear.easeNone
},'-=10')
.to('#lower', 10, {
stopColor:'#95DFFF',
ease:Linear.easeNone
})
.to('#upper', 10, {
stopColor:'#94DFFF',
ease:Linear.easeNone
},'-=10')
.to('#lower', 10, {
stopColor:'#f9b681',
ease:Linear.easeNone
})
.to('#upper', 10, {
stopColor:'#eb4a78',
ease:Linear.easeNone
},'-=10')
.fromTo('#sun', 10, {
fill:'#B30200'
},
{
fill:'#EC8323',
ease:Linear.easeNone
},'-=30')
.to('#sun', 10, {
fill:'#FFF',
ease:Linear.easeNone
},'-=20')
.to('#sun', 10, {
fill:'#fefdeb',
ease:Linear.easeNone
},'-=10')
.fromTo('#sun', 15, {
attr:{
cy:410,
r:105
}},{
attr:{
cy:0,
r:90
},
ease:Power1.easeInOut
},'-=30')
.to('#sun', 14, {
attr:{
cy:300,
r:105
},
ease:Sine.easeInOut
},'-=13')
.from('#mainCircleMask circle', 30, {
attr:{
r:500
},
ease:Power1.easeInOut
},'-=30')
var waterTl = new TimelineMax({paused:true});
waterTl.fromTo('#waterCircle', 30, {
fill:'#020111'
},{
fill:'#5DB3C6',
ease:Linear.easeNone
})
.fromTo('#waterRipple', 30, {
fill:'#020111'
},{
fill:'#A5DCE4',
ease:Linear.easeNone
},'-=30')
.fromTo('body', 30, {
backgroundColor:'#020111'
},{
backgroundColor:'#FFF',
ease:Linear.easeNone
},'-=30')
var skySunTween = TweenMax.to(skySunTl, 10, {
time:skySunTl.duration(),
ease:Power2.easeInOut
})
var waterTween= TweenMax.to(waterTl, 10, {
time:waterTl.duration(),
ease:Power2.easeInOut
})
mainTl.add(skySunTween, 0);
mainTl.add(waterTween, 0);
mainTl.timeScale(4);
mainTl.play(0)
//ScrubGSAPTimeline(mainTl)
//tl.timeScale(30)
Thank you

This should do the trick, using a mix of reversed:true in your TimelineMax() constructor. And also using progress(0.5) when you chain your timelines/tweens:
https://codepen.io/jonathan/pen/dNxgVK
I changed this:
var mainTl = new TimelineMax({
repeat:1,
yoyo:true,
repeatDelay:2
});
To this using reversed:true
var mainTl = new TimelineMax({
reversed:true
});
reversed is found in the TimelineMax Docs:
reversed ( value:Boolean ) : *
Gets or sets the animation's reversed state which indicates whether or
not the animation should be played backwards.
And i changed this
mainTl.add(skySunTween, 0);
mainTl.add(waterTween, 0);
mainTl.timeScale(4);
mainTl.play();
To this and added progress(0.5), which represents half way through the timeline
mainTl.add(skySunTween, 0);
mainTl.add(waterTween, 0);
mainTl.timeScale(4);
mainTL.progress(0.5); // added GSAP progress() method
mainTl.play();
.progress( value:Number, suppressEvents:Boolean ) : *
[override] Gets or sets the timeline's progress which is a value
between 0 and 1 indicating the position of the virtual playhead
(excluding repeats) where 0 is at the beginning, 0.5 is halfway
complete, and 1 is complete.
Resources:
progress(): https://greensock.com/docs/#/HTML5/GSAP/TimelineMax/progress/
TimelineMax: https://greensock.com/docs/#/HTML5/GSAP/TimelineMax/

Related

Phaser 3.17 doesn't setect collision between tilemap layer and player sprite

No collisions between map layer and player sprite. But collisions between world bounds work. What is wrong?
I tried different workarounds that could find online and none of them worked.
Game config
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: "#f",
physics: {
default: 'arcade',
arcade: {
gravity: { y: gameState.gravity },
debug: true
}
},
scene: {
preload,
create,
update
}
};
Code in create() regarding the tilemap and its layers and the character
gameState.map = this.add.tilemap('map');
gameState.dungeonTileset = gameState.map.addTilesetImage('dungeon', 'dungeonTiles');
gameState.backgroundLayer = gameState.map.createStaticLayer('Background', gameState.dungeonTileset);
gameState.mapLayer = gameState.map.createStaticLayer('Map', gameState.dungeonTileset);
gameState.miscLayer = gameState.map.createStaticLayer('Misc', gameState.dungeonTileset);
gameState.mapLayer.setCollisionByExclusion([-1]);
this.physics.world.bounds.width = gameState.mapLayer.width;
this.physics.world.bounds.height = gameState.mapLayer.height;
gameState.player = this.physics.add.sprite(73, 398, 'player', 0);
gameState.player.setCollideWorldBounds(true);
this.physics.add.collider(gameState.player, gameState.mapLayer);
No warning and no errors are coming up in the console. I don't know what to do anymore.
Thanks in advance!
I have addited a little bit the original example so you can see how it looks, I think the problem in your code is the line concerning gameState.mapLayer.setCollisionByExclusion([-1]); but am not sure because I can't see how the tilemap is created
var config = {
type: Phaser.WEBGL,
width: 800,
height: 576,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
loader: {
baseURL: 'https://labs.phaser.io',
crossOrigin: 'anonymous'
},
pixelArt: true,
physics: {
default: 'arcade',
arcade: { gravity: { y: 300 } }
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
var map;
var cursors;
var player;
var groundLayer;
function preload ()
{
this.load.image('ground_1x1', 'assets/tilemaps/tiles/ground_1x1.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/tile-collision-test.json');
this.load.image('player', 'assets/sprites/phaser-dude.png');
}
function create ()
{
map = this.make.tilemap({ key: 'map' });
var groundTiles = map.addTilesetImage('ground_1x1');
map.createDynamicLayer('Background Layer', groundTiles, 0, 0);
groundLayer = map.createDynamicLayer('Ground Layer', groundTiles, 0, 0);
groundLayer.setCollisionBetween(1, 25);//here
player = this.physics.add.sprite(80, 70, 'player')
.setBounce(0.1);
this.physics.add.collider(player, groundLayer);
cursors = this.input.keyboard.createCursorKeys();
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
this.cameras.main.startFollow(player);
}
function update ()
{
player.body.setVelocityX(0);
if (cursors.left.isDown)
{
player.body.setVelocityX(-200);
}
else if (cursors.right.isDown)
{
player.body.setVelocityX(200);
}
if (cursors.up.isDown && player.body.onFloor())
{
player.body.setVelocityY(-300);
}
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.17.0/dist/phaser.min.js"></script>

Creating table in canvas / Phaser 3 (Priority)

Can any body help with How to create Tables in Phaser-3(Priority) / Canvas.
Table like this.
Without styling is also ok. Just I want to know how we can create table in Phaser-3(Priority) / Canvas.
You can try to Rex UI Plugin
Here you can find a DEMO
Other demos (scrolling, fix-width-sizer and so on..) available HERE.
HTML
<footer><div id=version></div></footer>
CSS
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
background: #222;
color: #eee;
font: caption;
}
#version {
position: absolute;
left: 5px;
top: 605px;
}
JS
const Random = Phaser.Math.Between;
const COLOR_PRIMARY = 0x4e342e;
const COLOR_LIGHT = 0x7b5e57;
const COLOR_DARK = 0x260e04;
class Demo extends Phaser.Scene {
constructor() {
super({
key: 'examples'
})
}
preload() {
this.load.scenePlugin({
key: 'rexuiplugin',
url: 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/plugins/dist/rexuiplugin.min.js',
sceneKey: 'rexUI'
});
}
create() {
this.print = this.add.text(0, 0, '');
var db = createDataBase(400);
var tabs = this.rexUI.add.tabs({
x: 400,
y: 300,
panel: this.rexUI.add.gridTable({
background: this.rexUI.add.roundRectangle(0, 0, 20, 10, 10, COLOR_PRIMARY),
table: {
width: 250,
height: 400,
cellWidth: 120,
cellHeight: 60,
columns: 2,
mask: {
padding: 2,
},
},
slider: {
track: this.rexUI.add.roundRectangle(0, 0, 20, 10, 10, COLOR_DARK),
thumb: this.rexUI.add.roundRectangle(0, 0, 0, 0, 13, COLOR_LIGHT),
},
// scroller: true,
createCellContainerCallback: function (cell) {
var scene = cell.scene,
width = cell.width,
height = cell.height,
item = cell.item,
index = cell.index;
return scene.rexUI.add.label({
width: width,
height: height,
background: scene.rexUI.add.roundRectangle(0, 0, 20, 20, 0).setStrokeStyle(2, COLOR_DARK),
icon: scene.rexUI.add.roundRectangle(0, 0, 20, 20, 10, item.color),
text: scene.add.text(0, 0, item.id),
space: {
icon: 10,
left: 15
}
});
},
}),
leftButtons: [
createButton(this, 2, 'AA'),
createButton(this, 2, 'BB'),
createButton(this, 2, 'CC'),
createButton(this, 2, 'DD'),
],
rightButtons: [
createButton(this, 0, '+'),
createButton(this, 0, '-'),
],
space: {
leftButtonsOffset: 20,
rightButtonsOffset: 30,
leftButton: 1,
},
})
.layout()
//.drawBounds(this.add.graphics(), 0xff0000);
tabs
.on('button.click', function (button, groupName, index) {
switch (groupName) {
case 'left':
// Highlight button
if (this._prevTypeButton) {
this._prevTypeButton.getElement('background').setFillStyle(COLOR_DARK)
}
button.getElement('background').setFillStyle(COLOR_PRIMARY);
this._prevTypeButton = button;
if (this._prevSortButton === undefined) {
return;
}
break;
case 'right':
// Highlight button
if (this._prevSortButton) {
this._prevSortButton.getElement('background').setFillStyle(COLOR_DARK)
}
button.getElement('background').setFillStyle(COLOR_PRIMARY);
this._prevSortButton = button;
if (this._prevTypeButton === undefined) {
return;
}
break;
}
// Load items into grid table
var items = db
.chain()
.find({
type: this._prevTypeButton.text
})
.simplesort('id', {
desc: (this._prevSortButton.text === '-') // sort descending
})
.data();
this.getElement('panel').setItems(items).scrollToTop();
}, tabs);
// Grid table
tabs.getElement('panel')
.on('cell.click', function (cellContainer, cellIndex) {
this.print.text += cellIndex + ': ' + cellContainer.text + '\n';
}, this)
.on('cell.over', function (cellContainer, cellIndex) {
cellContainer.getElement('background')
.setStrokeStyle(2, COLOR_LIGHT)
.setDepth(1);
}, this)
.on('cell.out', function (cellContainer, cellIndex) {
cellContainer.getElement('background')
.setStrokeStyle(2, COLOR_DARK)
.setDepth(0);
}, this);
tabs.emitButtonClick('left', 0).emitButtonClick('right', 0);
}
update() {}
}
var createDataBase = function (count) {
var TYPE = ['AA', 'BB', 'CC', 'DD'];
// Create the database
var db = new loki();
// Create a collection
var items = db.addCollection('items');
// Insert documents
for (var i = 0; i < count; i++) {
items.insert({
type: TYPE[i % 4],
id: i,
color: Random(0, 0xffffff)
});
}
return items;
};
var createButton = function (scene, direction, text) {
var radius;
switch (direction) {
case 0: // Right
radius = {
tr: 20,
br: 20
}
break;
case 2: // Left
radius = {
tl: 20,
bl: 20
}
break;
}
return scene.rexUI.add.label({
width: 50,
height:40,
background: scene.rexUI.add.roundRectangle(0, 0, 50, 50, radius, COLOR_DARK),
text: scene.add.text(0, 0, text, {
fontSize: '18pt'
}),
space: {
left: 10
}
});
}
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Demo
};
var game = new Phaser.Game(config);

Transform too dense data

Trying to display line chart using plotly.js, my data are collected per second. I fed my graph but the result looks strange even if I zoom in, to very low detail where it should be displayed per seconds.
Are there any methods I could use to preprocess the data so it would display well in different scales (as I zoom in and out)?
var gd = document.getElementById('tester');
var layout = {
xaxis: {
showgrid: true,
tickformat: "%H:%M:%S",
},
margin: {
l: 40,
b: 40,
r: 30,
t: 20
},
hovermode: 'x',
};
var draw = function(data, layout) {
Plotly.newPlot(gd, data, layout, {
showLink: false,
displaylogo: false
});
};
var dataurl = 'https://gist.githubusercontent.com/fhurta/6c53839fbc91a363d62966a972a5e4a2/raw/2cd735f0b024e496164dacec92fa4a7abcd5da2e/series.csv';
Plotly.d3.csv(dataurl, function(rows) {
var data = [{
type: 'scatter',
x: rows.map(function(row) {
return new Date(row['Time']);
}),
y: rows.map(function(row) {
return row['Value1'];
}),
line: {
width: 1
}
}];
draw(data, layout);
});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="tester" style="width:600px;height:300px;"></div>

ZoomRange Highstock works not correct?

I made a Highstock diagramm and got aproblem with zooming on the yAxis.
I have a Button and 2 textfield to get the wanted min/max values for the axis. With min:0, max: 100 it works well. With min:0, max:80 it doesn't (max will still be 100 in the Diagramm).
If I use the mouse for zooming it works well (even a min of: 3.7 and a max of 3.894 is possible). But using the mouse is not an Option, because in the later Diagramm there will be 3 yAxes with individual zoom.
$(function () {
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 4
},
chart:{
zoomType: 'xy'
},
yAxis: [
{
labels: {
format: '{value}',
},
height: '100%',
opposite: false,
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
],
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
},
function(chart){
$('#btn').click(function(){
var min = temp_min.value,
max = temp_max.value;
chart.yAxis[0].setExtremes((min),(max));
});
});
}
$.each(names, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function (data) {
if(seriesCounter==0){
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
} else {
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
}
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});
JSFiddle
Another Question: Is it possible to set up a scrollbar for the yAxis as well?
Thanks for your help, Patrick
This is related with fact that tickInterval is not regular, so is rounded to value (like 100). The solution is using tickPositioner which calculates ticks, based on extremes which you define.
tickPositioner: function (min,max) {
var positions = [],
tick = Math.floor(min),
increment = Math.ceil((max - min) / 5);
for (tick; tick - increment <= max; tick += increment) {
positions.push(tick);
}
return positions;
},
http://jsfiddle.net/6s11kcwd/
The scrollbar is supported only for xAxis.

JsPlumb Dynamic Endpoints as Connection Overlays

I am trying to create dynamic endpoints as overlays on my connections and running into issues. I am trying to model what this person has here on SO:
jsPlumb connecting custom overlays - endpoint not moved
However, no matter what I try to do when I get to this point:
var overlay_div = $(connection.overlays[0].canvas);
I cannot get the connection to be recognized. I've tried to put this logic in the bind connection but that didn't work either when trying to establish the connection overlay. Any assistance on this would be extremely helpful.
http://jsfiddle.net/nitincool4urchat/c3b514wf/14/
First, Create custom elements as overlays
Second, Make sure that these elements have unique IDs
Third, Bind to the connection event to create endPoints on these custom-overlays.
jsPlumb.ready(function() {
// setup some defaults for jsPlumb.
instance = jsPlumb.getInstance({
Endpoint : ["Dot", {radius:2}],
HoverPaintStyle : {strokeStyle:"#1e8151", lineWidth:4 },
ConnectionOverlays : [
[ "Arrow", {
location:1,
id:"arrow",
length:14,
foldback:0.8
}]
,["Custom", {
create: function(component) {
return connectionNode();
},
location:0.5
}]
//,[ "Label", { label:"Connect To", id:"label", cssClass:"aLabel" }]
],
Container: "flowchart-demo"
});
var relationEndpoint = {
endpoint: ["Dot", { radius: 2 }],
isSource: true,
connector: ["Flowchart", { stub: [40, 60], cornerRadius: 5, alwaysRespectStubs: true }],
connectorStyle: { strokeStyle: "#5c96bc", lineWidth: 4, outlineColor: "transparent", outlineWidth: 4 },
maxConnections: 5,
onMaxConnections: function (info, e) {
alert("Maximum connections (" + info.maxConnections + ") reached");
},
isTarget: true,
dropOptions: {
tolerance: "touch",
hoverClass: "dropHover",
activeClass: "dragActive"
},
beforeDetach: function (conn) {
return confirm("Detach connection?");
}
};
function connectionNode() {
//var overlay_div = $(connection.ConnectionOverlays[0].canvas);
//jsPlumb.addEndpoint({ anchor: ["Perimeter", { shape: "Rectangle" }] }, relationEndpoint);
return $("<div>Custom</div>",{id:Date.now()}).css({border:'1px solid black',background:'green'});
}
var windows = jsPlumb.getSelector(".flowchart-demo .window");
instance.draggable(windows);
instance.bind("connection", function(info) {
console.dir(info.connection);
console.dir(info.connection.getOverlays());
console.dir(info.connection.getOverlays()[1].canvas);
var overlay_div = $(info.connection.getOverlays()[1].canvas);
jsPlumb.addEndpoint(overlay_div,{ anchor: ["Perimeter", { shape: "Rectangle" }] }, relationEndpoint);
});
// suspend drawing and initialise.
instance.doWhileSuspended(function() {
var isFilterSupported = instance.isDragFilterSupported();
// make each ".ep" div a source and give it some parameters to work with. here we tell it
// to use a Continuous anchor and the StateMachine connectors, and also we give it the
// connector's paint style. note that in this demo the strokeStyle is dynamically generated,
// which prevents us from just setting a jsPlumb.Defaults.PaintStyle. but that is what i
// would recommend you do. Note also here that we use the 'filter' option to tell jsPlumb
// which parts of the element should actually respond to a drag start.
// here we test the capabilities of the library, to see if we
// can provide a `filter` (our preference, support by vanilla
// jsPlumb and the jQuery version), or if that is not supported,
// a `parent` (YUI and MooTools). I want to make it perfectly
// clear that `filter` is better. Use filter when you can.
if (isFilterSupported) {
instance.makeSource(windows, {
filter:".ep",
anchor:"Continuous",
connector: ["Flowchart", { stub: [40, 60], cornerRadius: 5, alwaysRespectStubs: true }],
connectorStyle:{ strokeStyle:"#5c96bc", lineWidth:4, outlineColor:"transparent", outlineWidth:4 },
maxConnections:5,
onMaxConnections:function(info, e) {
alert("Maximum connections (" + info.maxConnections + ") reached");
}
});
}
else {
var eps = jsPlumb.getSelector(".ep");
for (var i = 0; i < eps.length; i++) {
var e = eps[i], p = e.parentNode;
instance.makeSource(e, {
parent:p,
anchor:"Continuous",
connector: ["Flowchart", { stub: [40, 60], cornerRadius: 5, alwaysRespectStubs: true }],
connectorStyle:{ strokeStyle:"#5c96bc",lineWidth:4, outlineColor:"transparent", outlineWidth:4 },
maxConnections:5,
onMaxConnections:function(info, e) {
alert("Maximum connections (" + info.maxConnections + ") reached");
}
});
}
}
});
// initialise all '.w' elements as connection targets.
instance.makeTarget(windows, {
dropOptions:{ hoverClass:"dragHover" },
anchor:"Continuous",
allowLoopback:true,
anchor:"Continuous"
});
jsPlumb.fire("jsPlumbDemoLoaded", instance);
});

Resources