如何在画布对象中保持图像的宽高比 [英] How to maintain aspect ratio of an image within a canvas object

查看:107
本文介绍了如何在画布对象中保持图像的宽高比的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于长宽比的快速问题,这让我有点头疼。我的画布元素的尺寸固定为250x250(1:1的比例)。然而,我绘制到画布中的图像可能是任何大小/比率。显然,如果我试图强制图像为250x250它看起来扭曲。

Quick question regarding aspect ratios that are driving me a bit nuts. My canvas element has fixed dimensions of 250x250 (1:1 ratio). The image that I'm drawing into the canvas however could possibly be any size/ratio. Obviously if I try to force the image to be 250x250 it looks distorted.

我试图让它尊重宽高比,但我现在在画布对象有一个奇怪的重叠,我的悬停效果是有点关闭。我的数学是错误的或我如何应用它的图像/画布是错误的。任何帮助或建议将非常感谢。

I've attempted to make it respect the aspect ratio but I get a strange overlap in the canvas object now and my hover effect is a bit off because of it. My math is either wrong or how I'm applying it to the image/canvas is wrong. Any help or suggestions would be greatly appreciated.

http: //jsfiddle.net/Ra9KQ/1/

var NameSpace = NameSpace || {};

NameSpace.Pixelator = (function() {

    var _cache = {
        'wrapper' : null,
        'canvas'  : null,
        'ctx'     : null,
        'img'     : new Image()
    },

    _config = {
        'canvasWidth'      : 250,
        'canvasHeight'     : 250,
        'isPlaying'        : false,
        'distortMin'       : 3,
        'distortMax'       : 100,
        'distortValue'     : 100, // matches distortMax by default
        'initDistortValue' : 3,
        'speed'            : 2.5,
        'delta'            : 2.5,   // delta (+/- step), matches speed by default
        'animation'        : null,
        'origImgWidth'     : null,
        'origImgHeight'    : null,
        'imgHeightRatio'   : null,
        'imgWidthRatio'    : null,
        'newImgWidth'      : null,
        'newImgHeight'     : null
    },

    _init = function _init() {

        _setupCache();
        _setupCanvas();
        _setupImage();

    },

    _setupCache = function _setupCache() {

        _cache.wrapper = $('#dummy-wrapper');
        _cache.canvas = document.getElementById('dummy-canvas');
        _cache.ctx = _cache.canvas.getContext('2d');

    },

    _setupCanvas = function _setupCanvas() {

        _cache.ctx.mozImageSmoothingEnabled = false;
        _cache.ctx.webkitImageSmoothingEnabled = false;
        _cache.ctx.imageSmoothingEnabled = false;

    },

    _setupImage = function _setupImage() {

        $(_cache.img).on('load', function() {

            _adjustImageScale();
            _pixelate();
            _assignEvents();

        });

        _cache.img.src = _cache.canvas.getAttribute('data-src');

    },

    _adjustImageScale = function _adjustImageScale() {

        var scaledHeight,
            scaledWidth;

        _config.origImgWidth = _cache.img.width;
        _config.origImgHeight = _cache.img.height;
        _config.imgHeightRatio = _config.origImgHeight / _config.origImgWidth;
        _config.imgWidthRatio = _config.origImgWidth / _config.origImgHeight;

        scaledHeight = Math.round(250 * _config.imgHeightRatio);
        scaledWidth = Math.round(250 * _config.imgWidthRatio);

        if (scaledHeight < 250) {

            _config.newImgHeight = 250;
            _config.newImgWidth = Math.round(_config.newImgHeight * _config.imgWidthRatio);

        } else if (scaledWidth < 250) {

            _config.newImgWidth = 250;
            _config.newImgHeight = Math.round(_config.newImgWidth * _config.imgHeightRatio);

        }

    },

    _assignEvents = function _assignEvents() {

        _cache.wrapper.on('mouseenter', _mouseEnterHandler);
        _cache.wrapper.on('mouseleave', _mouseLeaveHandler);

    },

    _mouseEnterHandler = function _mouseEnterHandler(e) {

        _config.delta = -_config.speed;

        if (_config.isPlaying === false) {
            _config.isPlaying = true;
            _animate();
        }

    },

    _mouseLeaveHandler = function _mouseLeaveHandler(e) {

        _config.delta = _config.speed;

        if (_config.isPlaying === false) {
            _config.isPlaying = true;
            _animate();
        }

    },

    _pixelate = function _pixelate(val) {

        var size = val ? val * 0.01 : 1,
            w = Math.ceil(_config.newImgWidth * size),
            h = Math.ceil(_config.newImgHeight * size);

        _cache.ctx.drawImage(_cache.img, 0, 0, w, h);

        _cache.ctx.drawImage(_cache.canvas, 0, 0, w, h, 0, 0, _config.canvasWidth, _config.canvasHeight);

    },

    _animate = function _animate() {

        // increase/decrese with delta set by mouse over/out
        _config.distortValue += _config.delta;

        if (_config.distortValue >= _config.distortMax || _config.distortValue <= _config.distortMin) {

            _config.isPlaying = false;
            cancelAnimationFrame(_config.animation);
            return;

        } else {

            // pixelate
            _pixelate(_config.distortValue);
            _config.animation = requestAnimationFrame(_animate);

        }

    };

    return {
        init: _init
    };

})();

NameSpace.Pixelator.init();


推荐答案

您的代码示例 w * _config.canvasWidth * _config.canvasHeight 区域,它是正方形。以下更改似乎为我修复了您的示例:

Your code samples w*h region, which is not square, into _config.canvasWidth*_config.canvasHeight region, which is square. Following change seems to fix your example for me:

// old code
_cache.ctx.drawImage(_cache.canvas, 0, 0, w, h, 0, 0, _config.canvasWidth, _config.canvasHeight);
// new code
_cache.ctx.drawImage(_cache.canvas, 0, 0, w, h, 0, 0, _config.newImgWidth, _config.newImgHeight);

这篇关于如何在画布对象中保持图像的宽高比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆