Подтвердить что ты не робот

QML Canvas: различное поведение при рендеринге

Я пытаюсь привлечь сектор кольцевого пространства в QML, используя объект Canvas. Во-первых, я написал код javascript, и я убедился, что это правильно, выполнив его в браузере.

Вот он:

var can = document.getElementById('myCanvas');
var ctx=can.getContext("2d");
var center = {
  x: can.width / 2,
  y: can.height / 2
};
var minRad = 100;
var maxRad = 250;

var startAngle = toRad(290);
var endAngle = toRad(310);

drawAxis();
drawSector();

function drawSector() {
  var p1 = {
    x: maxRad * Math.cos(startAngle),
    y: maxRad * Math.sin(startAngle)
  }
  p1 = toCanvasSpace(p1);

  var p2 = {
    x: minRad * Math.cos(startAngle),
    y: minRad * Math.sin(startAngle)
  }
  p2 = toCanvasSpace(p2);

  var p3 = {
    x: minRad * Math.cos(endAngle),
    y: minRad * Math.sin(endAngle)
  }
  p3 = toCanvasSpace(p3);
  var p4 = {
    x: maxRad * Math.cos(endAngle),
    y: maxRad * Math.sin(endAngle)
  }
  p4 = toCanvasSpace(p4);

  ctx.beginPath();
  ctx.moveTo(p1.x, p1.y);
  ctx.arc(center.x, center.y, maxRad, startAngle, endAngle);
  ctx.lineTo(p3.x, p3.y);
  ctx.arc(center.x, center.y, minRad, endAngle, startAngle, true);
  ctx.closePath();

  ctx.strokeStyle = "blue";
  ctx.lineWidth = 2;
  ctx.stroke();
}


function drawAxis() {
  ctx.beginPath();
  ctx.moveTo(can.width / 2, 0);
  ctx.lineTo(can.width / 2, can.height);
  ctx.stroke();
  ctx.beginPath();
  ctx.moveTo(0, can.height / 2);
  ctx.lineTo(can.width, can.height / 2);
  ctx.stroke();
}

function toRad(degrees) {
  return degrees * Math.PI / 180;
}

function toCanvasSpace(p) {
  var ret = {};
  ret.x = p.x + can.width / 2;
  ret.y = p.y + can.height / 2;
  return ret;
}

Здесь вы можете запустить код выше. Вывод:

введите описание изображения здесь

Затем я переместил один и тот же код в объект Canvas в Qml.

См. здесь main.qml, содержащий Canvas:

import QtQuick 2.5
import QtQuick.Window 2.2

Window {
    visible: true
    width: 500
    height: 500
    x:500

    Canvas
    {
        id: can
        anchors.fill: parent
        antialiasing: true



        onPaint: {
            var ctx=can.getContext("2d");

            var center = {
                x: can.width / 2,
                y: can.height / 2
            };
            var minRad = 100;
            var maxRad = 250;

            var startAngle = toRad(290);
            var endAngle = toRad(310);

            drawAxis();
            drawSector();

            function drawSector() {
                var p1 = {
                    x: maxRad * Math.cos(startAngle),
                    y: maxRad * Math.sin(startAngle)
                }
                p1=toCanvasSpace(p1);

                var p2 = {
                    x: minRad * Math.cos(startAngle),
                    y: minRad * Math.sin(startAngle)
                }
                p2=toCanvasSpace(p2);

                var p3 = {
                    x: minRad * Math.cos(endAngle),
                    y: minRad * Math.sin(endAngle)
                }
                p3=toCanvasSpace(p3);
                var p4 = {
                    x: maxRad * Math.cos(endAngle),
                    y: maxRad * Math.sin(endAngle)
                }
                p4=toCanvasSpace(p4);

                ctx.beginPath();
                ctx.moveTo(p1.x, p1.y);
                ctx.arc(center.x, center.y, maxRad, startAngle, endAngle);
                ctx.lineTo(p3.x, p3.y);
                ctx.arc(center.x, center.y, minRad, endAngle, startAngle, true);
                ctx.closePath();

                ctx.strokeStyle="blue";
                ctx.lineWidth=2;
                ctx.stroke();
            }


            function drawAxis() {
                ctx.beginPath();
                ctx.moveTo(can.width / 2, 0);
                ctx.lineTo(can.width / 2, can.height);
                ctx.stroke();
                ctx.beginPath();
                ctx.moveTo(0, can.height / 2);
                ctx.lineTo(can.width, can.height / 2);
                ctx.stroke();
            }

            function toRad(degrees) {
                return degrees * Math.PI / 180;
            }

            function toCanvasSpace(p) {
                var ret = {};
                ret.x = p.x + can.width / 2;
                ret.y = p.y + can.height / 2;
                return ret;
            }


        }
    }
}

В этом случае я получаю этот вывод:

введите описание изображения здесь

Как вы видите, в нижней части есть несовершенство.

Я действительно не понимаю, почему это несовершенство; более того, я не понимаю, почему один и тот же код дает разные результаты.

Любая помощь приветствуется! Благодаря

4b9b3361

Ответ 1

lineTo p3 не требуется, потому что, когда сегмент arc рисуется, соединительная линия рисуется автоматически в соответствии со спецификациями Canvas:

Метод arc() эквивалентен методу эллипса() в случае где два радиуса равны. [...]

Когда вызывается метод ellipse(), он должен действовать следующим образом. Во-первых, , если путь объекта имеет какие-либо подпуты, тогда метод должен добавить прямая линия из последней точки в подпуте к начальной точке дуги.

Кроме того, moveTo p1 не требуется, потому что это будет сделано как часть первой дуги.

Что касается того, почему дополнительная строка выводится дальше, чем начало второй дуги, это может быть ошибка в Qt (возможно, деление на 0 проблема - просто гадание здесь), или, может быть, вы просто не вычислили его положение правильно.