0

描画された図形を自動調整して自動中央揃えするキャンバスを作成したいと考えています。

私は持っている:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />

    <title>Fit Canvas Content</title>

</head>

<body>
    <canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
        Your browser doesn't support the HTML5 canvas.
    </canvas>
    <script>
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");
        ctx.fillStyle = "black";
        ctx.fillRect(-5, -50, 10, 100);
        ctx.fillRect(-50, -5, 100, 10);
    </script>
</body>
</html>

キャンバスのコンテンツは動的であり、形状は任意の場所に配置でき、任意のサイズにすることができることに注意してください。

キャンバス上の図形のコレクション

4

2 に答える 2

1

私はあなたがそのようなものが欲しいと思います: http://jsfiddle.net/e3qSP/1/

JSDoc が含まれているプラ​​スを描画するために使用される関数は次のとおりです。

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "black";
drawPlus(20, c);

/**
 * Draws plus in the middle of the canvas with specified width
 *
 * @public
 * @param {number} plusWidth The width of the plus
 * @param {canvas} canvas The canvas on which the plus should be drawn
 */
function drawPlus(plusWidth, canvas) {
    var height = parseInt(canvas.height),
        width = parseInt(canvas.width),
        size = Math.min(height, width);
    ctx.fillRect((width - plusWidth) / 2, (height - size) / 2, plusWidth, size);
    ctx.fillRect((width - size) / 2, (height - plusWidth) / 2, size, plusWidth);
}
于 2013-01-19T16:19:23.977 に答える
1

This will fit and scale to the canvas. Note that there is no padding, but thats easy to add

Firstly, you need to setup something to track transforms.

this.trackTransforms = function (ctx) {
    var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
    var xform = svg.createSVGMatrix();
    ctx.getTransform = function () { return xform; };

    var savedTransforms = [];
    var save = ctx.save;

    ctx.save = function () {
        savedTransforms.push(xform.translate(0, 0));
        return save.call(ctx);
    };

    var restore = ctx.restore;
    ctx.restore = function () {
        xform = savedTransforms.pop();
        return restore.call(ctx);
    };

    var scale = ctx.scale;
    ctx.scale = function (sx, sy) {
        xform = xform.scaleNonUniform(sx, sy);
        return scale.call(ctx, sx, sy);
    };

    var rotate = ctx.rotate;
    ctx.rotate = function (radians) {
        xform = xform.rotate(radians * 180 / Math.PI);
        return rotate.call(ctx, radians);
    };

    var translate = ctx.translate;
    ctx.translate = function (dx, dy) {
        xform = xform.translate(dx, dy);
        return translate.call(ctx, dx, dy);
    };

    var transform = ctx.transform;
    ctx.transform = function (a, b, c, d, e, f) {
        var m2 = svg.createSVGMatrix();
        m2.a = a; m2.b = b; m2.c = c; m2.d = d; m2.e = e; m2.f = f;
        xform = xform.multiply(m2);
        return transform.call(ctx, a, b, c, d, e, f);
    };

    var setTransform = ctx.setTransform;
    ctx.setTransform = function (a, b, c, d, e, f) {
        xform.a = a;
        xform.b = b;
        xform.c = c;
        xform.d = d;
        xform.e = e;
        xform.f = f;
        return setTransform.call(ctx, a, b, c, d, e, f);
    };

    var pt = svg.createSVGPoint();
    ctx.transformedPoint = function (x, y) {
        pt.x = x; pt.y = y;
        return pt.matrixTransform(xform.inverse());
    }
}

Next you need to be able to actually fit the contents. My function assumes you know the absolute width and height of the contents, you'll have to figure this out yourself but should be fairly easy. Note that if something starts at -150 and goes to +150, its width is 300.

this.fitToContents = function (widthOfContents, heightOfContents) {

    var p1 = this.context.transformedPoint(0, 0);
    var p2 = this.context.transformedPoint(this.canvas.width, this.canvas.height);

    var centerX = (p2.x - p1.x) / 2;
    var centerY = (p2.y - p1.y) / 2;

    centerX -= widthOfContents / 2;
    centerY -= heightOfContents / 2;

    this.context.translate(centerX, centerY);

    var lastX = this.canvas.width / 2,
        lastY = this.canvas.height / 2;

    var scaleFactorX = this.canvas.width / widthOfContents;
    var scaleFactorY = this.canvas.height / heightOfContents;

    var scaleFactorToUse = Math.abs(scaleFactorX) < Math.abs(scaleFactorY) ? scaleFactorX : scaleFactorY;

    var pt = this.context.transformedPoint(lastX, lastY);
    this.context.translate(pt.x, pt.y);
    this.context.scale(scaleFactorToUse, scaleFactorToUse);
    this.context.translate(-pt.x, -pt.y);
}

Putting it together itll look something like this:

this.init = function (elementId) {
    this.canvas = document.getElementById(elementId);
    this.context = this.canvas.getContext('2d');

    this.trackTransforms(this.context);

    this.context.canvas.width = this.canvas.offsetWidth;
    this.context.canvas.height = this.canvas.offsetHeight;

    this.draw();
}

this.draw = function () {

    this.fitToContents(300,300);

    // you can now draw other stuff
    // you can probably only fit to contents once, 
    // in the init function, if their positions don't change
    this.drawStuff();
}
于 2015-09-07T10:43:45.577 に答える