UNPKG

gl2d

Version:

2D graphics package for WebGL

178 lines 7.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var mat4_1 = require("../struct/mat4"); var rect_1 = require("../struct/rect"); var vec2_1 = require("../struct/vec2"); /** * Defines an orthographic projection from target space to clip space. */ var Camera = (function () { /** * Creates a camera restricted to the specified target area, and by the min/max zoom values. * @param target the area this camera is targeting. * @param minZoom the minimum zoom for the camera. * @param maxZoom the maximum zoom for the camera. */ function Camera(target, minZoom, maxZoom) { /** * The area of the target that is currently in view. */ this.view = new rect_1.RectStruct(); /** * The orthographic projection matrix that puts the target in view. */ this.matrix = new mat4_1.Mat4Struct(); /** * The current position of the camera in relation to the center of the target. */ this.position = new vec2_1.Vec2Struct(); /** * The current zoom setting for this camera. */ this.zoom = 1; this.target = target; this.minZoom = minZoom; this.maxZoom = maxZoom; } /** * Sets the size of the viewport in which the camera image will be displayed. * The resulting image will be centered inside the viewport and will match the aspect of the camera's target. * @param vw the new width of the viewport. * @param vh the new height of the viewport. */ Camera.prototype.setViewport = function (vw, vh) { // Destructure var _a = this, target = _a.target, view = _a.view; // Clear camera settings view.set(target); // Compute width and height of target var ww = target.width(); var wh = target.height(); // Compute width to height ratio of viewport and target var vr = vw / vh; var wr = ww / wh; // If viewport width ratio less than canvas width ratio if (wr < vr) { // Increase width so that ratios are equal view.scale(vr / wr, 1); } else { // Otherwise increase height so that ratios are equal view.scale(1, wr / vr); } // Restore camera settings view.stretch(1 / this.zoom); view.offset(this.position); // Update matrix to reflect changes this.updateMatrix(); }; /** * Sends a request to offset this camera by the desired vector. * Note: the desired offset may be adjusted to keep the camera from viewing anything outside of the target area. * @param desiredOffset the desired offset. * @returns the actual offset. */ Camera.prototype.offset = function (desiredOffset) { var targetPosition = vec2_1.Vec2.create(this.position); targetPosition.add(desiredOffset); // Determine how far we can position the camera away from the origin var far = rect_1.Rect.create(this.target); // Copy target boundaries far.mulScalar((this.zoom - this.minZoom) / this.zoom); // Determine max allowable size given zoom far.offset$(-far.centerX(), -far.centerY()); // Center at origin so we know how far left, up, right, and down we can go var actualOffset = vec2_1.Vec2.create(desiredOffset); // If target position is too far left if (targetPosition.x < far.left) { // Adjust offset so that offset.x + position.x = far.left actualOffset.x = far.left - this.position.x; } else if (targetPosition.x > far.right) { // Adjust offset so that offset.x + position.x = far.right actualOffset.x = far.right - this.position.x; } // If target position is too far down if (targetPosition.y < far.bottom) { // Adjust offset so that offset.y + position.y = far.bottom actualOffset.y = far.bottom - this.position.y; } else if (targetPosition.y > far.top) { // Adjust offset so that offset.y + position.y = far.top actualOffset.y = far.top - this.position.y; } // Now we can safely apply offset to our projection region this.view.offset(actualOffset); // And update our position variable accordingly this.position.add(actualOffset); // Return actual offset so caller can check if it differs from desired return actualOffset; }; /** * Sends a request to zoom in this camera by the desired scale factor. * Note: the desired scale factor is automatically adjusted to keep the camera from viewing anything outside of the target area. * @param desiredScaleFactor the desired scale factor. * @returns the actual scale factor. */ Camera.prototype.zoomIn = function (desiredScaleFactor) { var targetZoom = this.zoom * desiredScaleFactor; var actualScaleFactor; if (targetZoom < this.minZoom) { // Adjust scale factor so that zoom * changeInZoom = minZoom actualScaleFactor = this.minZoom / this.zoom; this.zoom = this.minZoom; } else if (targetZoom > this.maxZoom) { // Adjust scale factor so that zoom * changeInZoom = maxZoom actualScaleFactor = this.maxZoom / this.zoom; this.zoom = this.maxZoom; } else { // No need to adjust scale factor actualScaleFactor = desiredScaleFactor; this.zoom = targetZoom; } this.view.stretch(1 / actualScaleFactor); return actualScaleFactor; }; /** * Sends a request to zoom out this camera by the desired scale factor. * Note: the desired scale factor is automatically adjusted to keep the camera from viewing anything outside of the target area. * @param desired the desired scale factor. * @returns the actual scale factor. */ Camera.prototype.zoomOut = function (desiredScaleFactor) { return this.zoomIn(1 / desiredScaleFactor); }; /** * Sends a request to zoom this camera by the desired scale factor. * Note: the desired scale factor is automatically adjusted to keep the camera from viewing anything outside of the target area. * @param desired the desired scale factor. * @param focus the focus point. * @returns the actual scale factor and offset. */ Camera.prototype.zoomToPoint = function (desiredScaleFactor, focus) { var view = this.view; // Convert (x,y) coordinates to [0,1] space var normX = (focus.x - view.left) / view.width(); var normY = (focus.y - view.bottom) / view.height(); // Apply scale factor var actualScaleFactor = this.zoomIn(desiredScaleFactor); // Determine position of focus point after change in zoom var aft = new vec2_1.Vec2(); aft.x = view.left + (normX * view.width()); aft.y = view.bottom + (normY * view.height()); // Compute offset back to focus point var offset = vec2_1.Vec2.fromPointToPoint(aft, focus); // Apply the offset var actualOffset = this.offset(offset); // Return actual scale factor and offset so caller can check if they differ from desired return { scaleFactor: actualScaleFactor, offset: actualOffset }; }; /** * Recalculates the projection matrix to reflect changes in the camera settings. */ Camera.prototype.updateMatrix = function () { this.matrix.ortho(this.view, 0.1, 10); }; return Camera; }()); exports.Camera = Camera; //# sourceMappingURL=camera.js.map