2016-02-23 3 views
3

Я рисую линейную диаграмму с холстом. Диаграмма является отзывчивой, но линия должна иметь фиксированную ширину.Отзывчивый холст с фиксированной шириной линии

Я сделал это отзывчив с CSS

#myCanvas{ 
     width: 80%; 
    } 

, поэтому ход масштабируется.

Единственное решение, которое я нашел, это получить значение lineWidth с соотношением между атрибутом width холста и его реальной шириной. Чтобы применить его, я очищаю и рисую холст при изменении размера.

<canvas id="myCanvas" width="510" height="210"></canvas> 

<script type="text/javascript"> 
    var c = document.getElementById("myCanvas"); 
    var ctx = c.getContext("2d"); 
    function draw(){ 
     var canvasattrwidth = $('#myCanvas').attr('width'); 
     var canvasrealwidth = $('#myCanvas').width(); 
     // n sets the line width 
     var n = 4; 
     var widthStroke = n * (canvasattrwidth/canvasrealwidth) ; 
     ctx.lineWidth = widthStroke; 
     ctx.beginPath(); 
     ctx.moveTo(0 , 10); 
     ctx.lineTo(200 , 100); 
     ctx.stroke(); 
    } 
    $(window).on('resize', function(){ 
     ctx.clearRect(0, 0, c.width, c.height); 
     draw(); 
    }); 
    draw(); 
</script> 

Это мой первый холст, и я думаю, что есть простой способ сделал LineWidth фиксированной (не ясно и рисовать каждый раз на изменение размера), но я не могу найти его.

Существует вопрос с подобной проблемой

html5 canvas prevent linewidth scaling , но со шкалой() метод, поэтому я не могу использовать это решение.

+1

Нет, перерисовка - это путь. Если вы каким-либо образом меняете то, что нарисовано на холсте (и не хотите рисовать поверх того, что уже на нем), вам нужно будет перерисовать. Вы хотите, чтобы линия оставалась той же ширины пикселя, что и размер, и это невозможно сделать без перерисовки. В любом случае, перерисовывание не очень облагается налогом на такие вещи, как графики. – Matt

ответ

3

Невозможно получить реальное измерение деталей для холста, например, миллиметров или дюймов, поэтому вам придется делать это в пикселях.

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

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

Если вы масштабируете график различными значениями в направлениях x и y, вам нужно будет использовать методы ctx.scale или ctx.setTransform. Как вы говорите, вы не хотите этого делать, я буду считать, что ваше масштабирование всегда имеет квадратный аспект.

Таким образом, мы можем выбрать самое низкое приемлемое разрешение. Скажем 512 пикселей для ширины или высоты холста и выберите lineWidth в пикселях для этого разрешения.

Таким образом, мы можем создать две константы

const NATIVE_RES = 512; // the minimum resolution we reasonably expect 
const LINE_WIDTH = 1; // pixel width of the line at that resolution 
         // Note I Capitalize constants, This is non standard in Javascript 

Тогда для расчета фактической ширины линии просто фактическая canvas.width разделенное на NATIVE_RES затем умножьте результат на LINE_WIDTH.

var actualLineWidth = LINE_WIDTH * (canvas.width/NATIVE_RES); 
ctx.lineWidth = actualLineWidth; 

Возможно, вы захотите ограничить этот размер до наименьшего размера холста. Вы можете сделать это с помощью Math.min или вы можете ограничить его в наибольшем размере с помощью Math.max

Для минимального размера.

var actualLineWidth = LINE_WIDTH * (Math.min(canvas.width, canvas.height)/NATIVE_RES); 
ctx.lineWidth = actualLineWidth; 

Для максимальной размерности

var actualLineWidth = LINE_WIDTH * (Math.max(canvas.width, canvas.height)/NATIVE_RES); 
ctx.lineWidth = actualLineWidth; 

Вы могли бы также рассмотреть диагонали как корректирующего коэффициента, который будет включать в себя лучшее из обоих х и у размеров.

// get the diagonal resolution 
var diagonalRes = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height) 
var actualLineWidth = LINE_WIDTH * (diagonalRes/NATIVE_RES); 
ctx.lineWidth = actualLineWidth; 

И, наконец, вы можете ограничить нижний предел линии, чтобы остановить странные артефакты, когда линия становится меньше, чем 1 пиксель.

Установить нижний предел, используя диагональный

var diagonalRes = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height) 
var actualLineWidth = Math.max(1, LINE_WIDTH * (diagonalRes/NATIVE_RES)); 
ctx.lineWidth = actualLineWidth; 

Это создаст отзывчивую ширину линии, которая не будет идти под 1 пикселем, если холст диагональ разрешение идет под 512.

метода вы используете вверх тебе. Попробуйте их посмотреть, что вам больше нравится. NATIVE_RES Я выбрал «512», также является произвольным и может быть тем, что вы пожелаете. Вам просто нужно поэкспериментировать со значениями и методами, чтобы увидеть, что вам больше всего нравится.

Если ваш аспект масштабирования меняется, тогда существует совершенно другая техника для решения этой проблемы, которую я оставлю для другого вопроса.

Надеюсь, это помогло.

Смежные вопросы