div rotates but div's clipping box does not

2019-07-28 23:58发布

问题:

Related fiddle

Trying to build this neat little meter without a JS library (like Raphael), I came up with a question you can find here. After much frustration, I thought of another layout with which to make this meter work (that worked around a separate known Chrome bug as well), which can be seen at the fiddle above.

<div id="clipper">
    <div id="round">
    </div>
    <div id="clipper2">
        <div id="meter"></div>
    </div>
</div>

However, this created a completely NEW Android (4.0.4 at least) browser defect. The clipping box div element rotates as expected. However, the actual calculated clipping box has horizontal and vertical boundaries, which encompass the visible shape. Essentially, it means that child elements are always clipped square, instead of along the rotated edges of the element.

The meter itself has some unusual requirements, else this would be easier to do: it's not a full half circle, but a slice off the top of an arc. It must also rotate around a point bottom center of this slice, not what would be the center of the circle.

回答1:

Try with SVG: http://jsfiddle.net/8fsS2/4/

HTML:

<svg id="generate" version="1.1" xmlns="http://www.w3.org/2000/svg"
    width="500px" height="120px" viewBox="0 0 200 120" preserveAspectRatio="none">
        <g id="chart"></g>
</svg>

Javascript:

function deg2rad(deg) {
        return deg * Math.PI / 180;
    }

    function annularSector(centerX, centerY, startAngle, endAngle, innerRadius, outerRadius) {
        startAngle = deg2rad(startAngle + 180);
        endAngle = deg2rad(endAngle + 180);

        var p = [
                [centerX + innerRadius * Math.cos(startAngle),  centerY + innerRadius * Math.sin(startAngle)]
            , [centerX + outerRadius * Math.cos(startAngle),    centerY + outerRadius * Math.sin(startAngle)]
            , [centerX + outerRadius * Math.cos(endAngle),      centerY + outerRadius * Math.sin(endAngle)]
            , [centerX + innerRadius * Math.cos(endAngle),      centerY + innerRadius * Math.sin(endAngle)]
            ];

        var angleDiff = endAngle - startAngle
            , largeArc = (angleDiff % (Math.PI * 2)) > Math.PI ? 1 : 0;

        var commands = [];

        commands.push("M" + p[0].join());
        commands.push("L" + p[1].join());
        commands.push("A" + [outerRadius, outerRadius].join() + " 0 " + largeArc + " 1 " + p[2].join());
        commands.push("L" + p[3].join());
        commands.push("A" + [innerRadius, innerRadius].join() + " 0 " + largeArc + " 0 " + p[0].join());
        commands.push("z");

        return commands.join(" ");
    }

    function create(type, attr, parent) {
        var element = document.createElementNS("http://www.w3.org/2000/svg", type);
        if (attr) for (var name in attr) element.setAttribute(name, attr[name]);
        if (parent) parent.appendChild(element);
        return element;
    }
    var svg = document.querySelector("svg#generate g#chart");
    create("path", {
        fill: "#FF0000",
        d: annularSector(80, 80, 0, 180, 0, 80)
    }, svg);


    create("path", {
        fill: "#00FF00",
        d: annularSector(80, 80, 0, 65, 0, 80)
    }, svg);

adjust the viewBox to scale.



回答2:

Android really, really doesn't like transform: translateZ(0);. At all. Anywhere. If this property is on any element in that tree, the whole thing fails.

Updated fiddle that works: http://jsfiddle.net/FB6rf/15/

If anyone has an explanation to this behavior, I'm all ears. Because otherwise *poof*, I'm out 100 bounty. Maybe if some users show me some love, it won't be such a big loss.