2014-01-15 2 views
1

Я пытаюсь масштабировать/перемещать путь SVG, созданный с помощью api Raphael. Я хочу, чтобы путь соответствовал аккуратно внутри контейнера, независимо от размера контейнера. Я искал ссылку, сеть, и я все еще изо всех сил пытаюсь заставить это работать.Путь Raphael изменяет размер и перемещается относительно контейнера

Если кто-нибудь скажет мне, почему это не работает, я был бы очень доволен.

Эта скрипка показывает вам, что я делаю: http://jsfiddle.net/tolund/3XPxL/5/

JavaScript:

var draw = function(size) { 
    var $container = $("#container").empty(); 
    $container.css("height",size+"px").css("width",size+"px"); 

    var paper = Raphael("container"); 

    var pathStr = "M11.166,23.963L22.359,17.5c1.43-0.824,1.43-2.175,"+ 
     "0-3L11.166,8.037c-1.429-0.826-2.598-0.15-2.598,"+ 
     "1.5v12.926C8.568,24.113,9.737,24.789,11.166,23.963z"; 

    // set the viewbox to same size as container 
    paper.setViewBox(0, 0, $container.width(), $container.height(), true); 

    // create the path 
    var path = paper.path(pathStr) 
     .attr({ fill: "#000", "stroke-width": 0, "stroke-linejoin": "round", opacity: 1 }); 

    // get the path outline box (may be different size than view box. 
    var box = path.getBBox(); 

    // move the path as much to the top/left as possible within container 
    path.transform("t" + 0 + "," + 0); 

    // get the width/height based on path box relative to paper (same size as container) 
    var w = (paper.width)/box.width; 
    var h = (paper.height)/box.height; 

    // scale the path to the container (use "..." to compound transforms) 
    path.transform('...S' + w + ',' + h + ',0,0'); 
} 

$(function() { 
    var currentSize = 30; 
    draw(currentSize); 

    $("#smaller").click(function(){ 
     currentSize = currentSize < 10 ? currentSize : currentSize * 0.5; 
     draw(currentSize); 
    }); 
    $("#bigger").click(function(){ 
     currentSize = 300 < currentSize ? currentSize : currentSize * 2; 
     draw(currentSize); 
    }); 
}); 

HTML:

<button id="smaller">-</button> 
<button id="bigger">+</button> 

<div id="container" style="border: 1px #ddd solid; margin: 30px"> 

</div> 

Спасибо, Torgeir.

+0

Странно, но я попытался использовать следующий код для scale coeff: 'var w = (paper.width)/box.width/2, h = (paper.height)/box.height/2' и выглядит как будто он работает. Проверьте это, пожалуйста. – vbo

+0

Спасибо, хакер, возможно, работал в некоторых случаях, но Кевин дал отличный ответ ниже. Мое понимание API Raphael было просто недостаточно хорошим. – Torgeir

ответ

4

Я думаю, что ваша проблема является фундаментальным непониманием того, для чего полезен viewbox. В вашем коде вы пытаетесь установить окно просмотра элемента svg так, чтобы оно соответствовало пространству координат экрана, а затем преобразуйте путь в соответствие с этим пространством координат. Нет никакой технической причины, по которой вы не можете этого сделать, но он действительно берет «Масштабируемый» из «Масштабируемой векторной графики». Вся точка окна просмотра - сделать перевод между векторным координатным пространством и относительным экраном.

Лучший способ решить вашу проблему состоит в том, чтобы не преобразовать путь в соответствие с элементом SVG, но использовать окно просмотра, чтобы позволить встроенной масштабируемости SVG сделать это за вас.

Прежде всего: создайте свой путь, чтобы у нас был объект для работы. Нас не интересует, что такое viewbox.

var pathStr = "..."; // The content of the path and its coordinates are completely immaterial 

var path = paper.path(pathStr) 
    .attr({ fill: "#000", "stroke-width": 0, "stroke-linejoin": "round", opacity: 1 }); 

Теперь все, что нам нужно сделать, это использовать ViewBox в «фокусе» SVG на координатном пространстве интересующих нас.

var box = path.getBBox();  
var margin = Math.max(box.width, box.height) * 0.1; // because white space always looks nice ;-) 
paper.setViewBox(box.x - margin, box.y - margin, box.width + margin * 2, box.height + margin * 2); 

И это все. SVG (независимо от его размера) будет переводить из внутренних координат, указанных в окне просмотра, в его физические координаты на экране.

Вот вилка вашей скрипки как proof-of-concept.

+0

Большое вам спасибо. Это очень полезный ответ. Я вижу, что я должен был потратить больше времени на документацию. – Torgeir

+0

Кстати, вы не знаете, почему это не внутри контейнера, если размер действительно маленький (я использую Chrome)? Я сомневаюсь, что мне нужно будет использовать этот небольшой размер, но если вам известно, почему, мне было бы интересно узнать ответ. – Torgeir

+0

Документация Барановского немного на проницательной стороне, когда дело доходит до преобразований и viewboxes ;-) Я думаю, что смещение происходит потому, что Raphael создает svg, который соответствует размерам контейнера *, включая границу *, но он смещается от область содержимого, расширяясь таким образом. Я даже не заметил его сначала, потому что добавлял маржу в уравнение с самого начала. –

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