davidfig / pixi-viewport Goto Github PK
View Code? Open in Web Editor NEWA highly configurable viewport/2D camera designed to work with pixi.js
Home Page: https://davidfig.github.io/pixi-viewport/
License: MIT License
A highly configurable viewport/2D camera designed to work with pixi.js
Home Page: https://davidfig.github.io/pixi-viewport/
License: MIT License
The current demo is good for testing, but the gui is way too confusing for anyone just trying out pixi-viewport for the first time. I was thinking of creating multiple demos that show off the plugins:
I also want to make the demos prettier. I'm tired of the square stars :)
With the latest npm build, I'm experiencing freezing of the viewport when trying to zoom with the mouse wheel. Probably related to the options.divWheel change.
According to the JSDocs, zoom should return Viewport
, but it doesn't return anything.
Which one should be changed, docs or implementation?
Line 660 in fbf5982
When snap-zoom is running and options.center = false
for snap the viewport misbehaves because it requires an Ease.to(...) object to have constantly updating inputs in order for snap to properly calculate the top left corner (this is because snap-zoom is constantly changing the scale of the viewport).
A possible but hacky solution is to "look ahead" to the final values of the snap-zoom plugin and use that x and y scale when calculating the targetX and targetY inputs of the Ease.to(...) object in the snap function.
Hai David thank you for your work.
Is there a way to make zoom become an animation instead of direct zoom?
For example when i use : zoomPercent(2,2)
Upon constructing the viewport, the option options.pauseOnBlur doesn't seem to do anything. Especially noticable with the follow, decelerate, and snap plugins. When switching to a different tab, I expect the plugins to still be constantly running when I set options.pauseOnBlur to false. However, the actual result is that pixi-viewport plugins halt until I switch back to the original tab.
In the viewport documentation, the drag-start event is incorrectly labelled as drag.
Hello Figatner, I noticed that the zoom calculation in the wheel event is calculated based in the current container scale value.
For example, let's say that the wheel event was initialized with a 2% value. If you zoom in a single time, the scale value will go to 1.02. But if you zoom out after it, it won't go back to 1, it will go back to 0.9996. Is this the expected behavior?
I have basic setup with pinch, drag, bounce, clampZoom and decelerate plugins.
Everything works fine, until the moment when i drag the stage and drag-end triggered on mobile browser search bar or bottom toolbar (need exactly release the finger) - stage just stuck. Drag completely stops, but pinch still works.
Tested this on IOS Safari / Chrome and Android Chrome browsers.
Bounce and Clamp are not working properly on bottom-right corner. Again.
When .bounce() is enabled, if the view-able area is smaller than the screen size then it will keep bouncing between the borders.
Definitely need to add a check for this.
A nitty-gritty improvement, by default the .wheel()
plugin will zoom out when scrolling up and zoom in when scrolling down (which is the opposite of what most scroll implementations do).
Easy fix is to do
.wheel({percent: -0.1})
but it would be nice to have this by default.
Mouse wheel should only interact with the viewport that it hovers over. (This will allow more than one viewport to work well on screen.)
I did some refactoring over the last few days and I wanted feedback/testing before merging with master. The changes are in the more-pixi branch.
There is one breaking change, and a bunch of under-the-hood changes:
Viewport is now a child of PIXI.Container. This means you no longer pass a container, but viewport is the container. This cleaned up some of the code. (I originally had it separate to avoid a peer dependency, but decided this was more robust.)
I removed the yy-loop and yy-input dependencies and now fully rely on PIXI.ticker and PIXI.interaction for all looping and interaction. This means viewport no longer ships with its own start/stop functionality. This had the added benefit of a significant perf improvement. Not sure if yy-loop was the culprit (I spent many hours trying to figure out what was going on). Either way, this is cleaner and more in line with a true PIXI library.
hitArea makes a return to set the hit area for the viewport. The hitArea defaults to the passed world size. You can also statically change it by setting options/viewport.forceHitArea
When you drag and release, the viewport is designed to have an effect where it gradually comes to a stop depending on the velocity of which you released it.
I found that after zooming in and out, the effect quickens and seemingly "teleports" the viewport to the end position rather than gradually coming to a stop there.
Here's a video that shows what I mean
https://youtu.be/JqgNEMeLg4Y
This is the code that I'm currently using to invoke the zoom
const maxHeight = 1000;
const minHeight = 100;
const zoomRate = 40 / 100;
function updateMouse(dx, dy, dz, ev) {
var currentHeight = viewport.bottom - viewport.top;
var newHeight = currentHeight + (zoomRate * dy);
viewport.fitHeight(Math.min(Math.max(newHeight, minHeight), maxHeight));
viewport.update();
}
require('mouse-wheel')(updateMouse, true);
And here's how I instantiate the viewport
var options = {
screenWidth: w * 2,
screenHeight: h,
worldWidth: w,
worldHeight: h,
};
var viewport = new Viewport(game.stage, options);
viewport
.drag()
.hitArea()
.decelerate()
.start();
Thanks!
Hi,
It seems that the zoom pointer position becomes off after auto resizing the canvas.
This happens when:
app.renderer.autoresize = true;
Here is what it looks like:
Here is the code:
var pixi_container = $('#pixi');
var w = pixi_container.innerWidth();
var h = $(document).innerHeight() - pixi_container.offset().top;
var [W, H] = [4 * 1024, 3 * 1024];
// create viewport
var viewport = new Viewport({
screenWidth: w,
screenHeight: h,
worldWidth: W,
worldHeight: H,
});
// add the viewport to the stage
var app = new PIXI.Application({
width: width,
height: height,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x00aabb
});
app.renderer.autoResize = true;
app.stage.addChild(viewport);
container.appendChild(app.view);
// activate plugins
viewport
.drag()
.clamp()
.pinch({ noDrag: true })
.wheel()
.clampZoom({ maxWidth: W, maxHeight: H, minWidth: w, minHeight: h })
.decelerate();
viewport.fit().resize(w, h, W, H);
viewport.moveCenter(W / 2, H / 2); // center viewport
// add a bunch of red boxes
for (let i = 0; i < 100; i++) {
var sprite = viewport.addChild(new PIXI.Sprite(PIXI.Texture.WHITE));
sprite.anchor.set(0.5);
sprite.tint = 0xff0000 * Math.random();
sprite.width = sprite.height = Math.random() * 200;
sprite.position.set(Math.random() * W, Math.random() * H);
}
The reason for this might be related to the autoResize
flag on the Pixi renderer being set as a CSS property, and the mouse coordinates not taking that into account.
What would be the simplest way to solve this?
Thanks for the help!
Hi, I have a suggestion for what I would guess is a common use case.
ClampZoom lets you clamp relative to the size of the viewport, but I'm interested in clamping relative to the container's scale so that the min and max zoom are always values that scale nicely, e.g. x0.5 to x2. Something along the lines of: new Viewport({...}).pinch().clampZoom({min: 0.5, max: 2});
. Allowing the same with snapZoom would be nice as well.
Maybe there's already a straightforward way of doing this with the current API that I'm missing.
^ Error occurs upon instantiation of a viewport.
Occurs in viewport.js on line 63.
Hi David,
I am getting following error with viewport. Your help is required.
node_modules/pixi-viewport/@types/index.d.ts (176,15): Class 'Viewport' incorrectly extends base class 'Container'.
Types of property 'on' are incompatible.
Type '{ (event: ViewportEventType, fn: (viewport: Viewport) => void, context?: any): this; (event: View...' is not assignable to type '{ (event:
"added" | "removed", fn: (displayObject: DisplayObject) => void, context?: any): this; ...'.
Types of parameters 'event' and 'event' are incompatible.
Type '"added" | "removed"' is not assignable to type 'ViewportEventType'.
Type '"added"' is not assignable to type 'ViewportEventType'.
Tested on Chrome Version 69.0.3464.0 (Official Build) dev (64-bit)
Dragging still works on phone touchscreens.
When using follow method - viewport shows areas beyond world box. I restrict viewport position by next lines inside the update method of the follow plugin:
this.parent.x = Math.min(this.parent.x, 0);
this.parent.y = Math.min(this.parent.y, 0);
this.parent.x = Math.max(this.parent.x, this.parent.screenWidth - this.parent.worldWidth);
this.parent.y = Math.max(this.parent.y, this.parent.screenHeight - this.parent.worldHeight);
Is there a better way to do this and maybe this should be done on a higher level?
When the viewport's parent scale is not 1, the input distance calculations are off.
For example, my current game uses a viewport within a scaled region. The drags are not scaled down to account for the parent's scale.
When the viewport is moved or dragged, the underlying hitArea for firing events moves with it.
E.g. I have a viewport with a box drawn with the top-left corner at 0, 0. Currently, I can click anywhere and the mouse click will fire the desired events.
Then I drag my viewport to the top and to the left...
Now I can only trigger events by clicking this area (highlighted in blue)
scaling of the viewport has the same effect. Zooming out makes the hitArea smaller on the user's screen and zooming in makes it larger
I am trying to figure out how to create a camera boundary, so it stops at a certain x and y value. Is this built in?
: )
I can't tell if I'm using the plugin incorrectly, or if there's a bug happening.
I'm using pixi-viewport 0.6.1.
Here's the general outline of what I'm doing, does anything significantly stand out?
var game = new PIXI.Application(600, 600, {
antialias: false,
transparent: false,
resolution: 1
});
const Viewport = require('pixi-viewport');
var viewport = new Viewport(game.stage);
viewport
.drag()
.pinch()
.hitArea()
.decelerate()
.bounce()
.start();
var bunny = new PIXI.Sprite(resources.bunny.texture);
bunny.x = game.renderer.width / 2;
bunny.y = game.renderer.height / 2;
var target = game.stage.addChild(bunny);
game.ticker.add(function () {
bunny.x += 5
console.log('x: ' + viewport.center.x + ' y: ' + viewport.center.y)
});
viewport.follow(bunny);
The fit plugin (in pull request) will not abide by the zooming boundries as set by the zlamp-zoom plugin.
The bug happens when the viewport is zoomed out past the max width/height or zoomed in past the min width/height by pinching (using the pinch
plugin)
Here's a live demo of the bug that you can try on a touchscreen of your own
https://www.student.cs.uwaterloo.ca/~smclose/bunny-pinch-error/
By default the viewport is set to its max height boundary, so zooming in works (until you hit the minHeight), and zooming out immediately causes the transformation bug.
Here's a video that showcases the bug: https://youtu.be/ims7iuUJwag
Here is the code that the website is running
require('pixi.js');
const Viewport = require('pixi-viewport');
const maxHeight = 1000;
const minHeight = 100;
var h = 600;
var w = 600;
// Creates the PIXI application
var game = new PIXI.Application(w, h, {
antialias: false,
transparent: false,
resolution: 1
});
// Sets up the element
game.view.style.position = "absolute";
game.view.style.display = "block";
document.body.appendChild(game.view);
game.renderer.autoResize = true;
game.renderer.backgroundColor = 0x00FFFF;
var options = {
screenWidth: w,
screenHeight: h,
worldWidth: w,
worldHeight: h,
};
var viewport = new Viewport(game.stage, options);
var scrollOptions = {
noDrag: false,
minWidth: 10,
minHeight: minHeight,
maxWidth: 1000000,
maxHeight: maxHeight,
}
viewport
.drag()
.hitArea()
.pinch(scrollOptions)
.decelerate()
.start();
// This creates a texture from a 'bunny.png' image.
PIXI.loader.add('bunny', 'game/bunny.png').load(function (loader, resources) {
var bunny = new PIXI.Sprite(resources.bunny.texture);
bunny.x = game.renderer.width / 2;
bunny.y = game.renderer.height / 2;
bunny.anchor.x = 0.5;
bunny.anchor.y = 0.5;
game.stage.addChild(bunny);
});
I was going to create a fork that transpiles to es5 since that was giving me issues with create react app. I figured I might end up submitting a PR for it (since it seems fairly benign and simple) so I might as well ask first.
I tried using browserify to accomplish this but I was having issues converting it to es5 on the fly, in the index file. I was easily able to do it on the command line (to publish it to docs). But that isn't the entry point on npm.
So I will likely use babel for it.
I don't mind trying to do this in different ways. : :)
If this sounds useful I will submit a PR.
It would nice to have a plugin that pans the screen at a certain speed when the mouse is within a certain margin of the screen edge.
Hi, i mentioned that if the center before snap is equal with center after snap, snap plugin will wait for center change before start, same behaviour with snapZoom plugin - if width for example before and after snapZoom is viewport.screenWidth / 3 plugin will wait for width change before start.
Is this expected behaviour and i should check for center and width before calling these plugins ?
How to build a bundle or minified version for browser?
This occurs after pinching with two fingers, each finger lifted fires a tap event.
It would be nice if the radius could be checked first then the speed option used if both are provided.
If you have wheel on center, and your object is at 0px (and the edge of the world is at 0px). Then zooming in zooms you into 0px, as opposed to screenwidth/2.
I would love to submit a PR to accomplish them but I may need some guidance.
I'm going to take this opportunity to fix the hacky implementation of touch counting
I encountered this issue with pixi-scrollbox
and yy-ui
. Whenever the WebGL Canvas element which contains PIXI does not start from 0,0
x/y in the browser window, the mouse events will not correctly offset. For example if I try to scroll down with the mouse wheel, then mouse events will trigger if my mouse is over 0,0
, which is not where the canvas is. Say the canvas is placed at 100,100
and is 300 in width and 300 in height. Well the mouse event will trigger at 0,0
where the canvas isn't even at, but it will not trigger at 400,400
where the canvas is, because it will be offset by it's browser window position.
It seems to understand where the PIXI.JS container/display object is relative to the start of the browser window x/y position, but NOT where the canvas actually is, resulting in all mouse events triggering only outside of the actual canvas if the canvas does not start perfectly at 0,0
in the browser.
Why is the mouse position calculated by where the mouse at relative to the browser window and not relative to where the canvas is placed / inside the canvas, and how can I fix that / correctly offset it?
Hi
I am getting 'Cannot find namespace 'PIXI'' error in index.d.ts file. Any workaround is available to this?
I am using it in Angular application.
versions:
"pixi-viewport": "^2.7.2",
"pixi.js": "^4.8.1",
I found squares in this live example shaked in my chrome browser with 'follow' option check on, but yy-viewport's demo seems work fine and smooth.
Sometimes the 'click' event fires twice when only clicking the mouse once. This behaviour is exhibited in the demo as well.
I'm using drag function, but app.stage.pivot.x is always same after dragging.
How can I check camera's x axis after drag?
Hi David,
First of all, great little library with a lot of handy features! well done!
I'm only missing a definitions file for Typescript projects, where I have to import * as Viewport from "pixi-viewport";
and put a // @ts-ignore
on top of it so that it doesn't complain about Viewport having any
type.
I'm sure many others will find @types/pixi-viewport
npm package useful. I don't have too much experience with publishing packages on npm, especially for types, but I'm willing to help.
Keep up the great work!
Gio
When a user clicks on an object it'd be nice to choose an easing. For example, a sinusoidal easing so that if the object is far from the center it will quickly move and slow down as it starts to approach the center the object.
This may present some difficulty, as contrary to the snap plugin, the follow plugin will need to account for moving object where the desired target coordinates are constantly changing.
All the moved should not be mixed together
drag-end
drag-start
There should be one ๏ผ drag-moved
The drag process should also have an independent event
Hi, is there a way to detect current world screen width / height while user pinching the screen ?
Thx for such a great library!
I'm activating the viewport with drag(), pinch(), bounce(), wheel() and decelerate().
I start to drag normally, but make the drop outside the browser area (tried on iPhone Safari, but the same happens on Chrome when simulating a device).
From that point on, the viewport is neither clickable nor draggable (but strangely remains pinch-able), and the page has to be refreshed by the user.
I'm using version [email protected]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.