2013-05-24 3 views
2

Проблема очень проста в описании. У меня простая форма SVG закрыта, например:Случайная точка внутри SVG <path>

<path d="M435.95,147.99l0.33,0.49l-0.11,1.07l-0.39,0.04l-0.29,-0.15l0.21,-1.4l0.25,-0.05Z"></path> 

Я хочу нарисовать точку в случайном порядке, где-то внутри этой формы.

Как это сделать? Я надеюсь, что решение будет максимально простым.

+0

Является ли ваша форма гарантированной выпуклой, или она может иметь вогнутые области? – Phrogz

+0

Я отредактировал ваш заголовок у _ "на SVG' '' _ (что просто) для _ "внутри SVG' '' _, так как вы написали это в вопросе. Если вам действительно нужна только случайная точка вдоль границы формы, отредактируйте ее. – Phrogz

+1

Может быть вогнутым. Спасибо за редактирование, вы правы, если бы я хотел только точку вдоль границы, я бы использовал getPointAtLength() со случайным числом. –

ответ

5

Вы можете использовать getBBox, чтобы получить ограничительную рамку пути и создать случайную точку в этом диапазоне. Затем используйте elementFromPoint со случайной точкой, чтобы проверить, что вы действительно находитесь над формой.

Если какие-либо элементы охватывают путь, то установите для них указатель-события = "none", чтобы они игнорировались, когда вы это делаете.

+0

Это отличная идея, просто часть проверки пересечения немного «хакерская». Иногда требуемый элемент отсутствует в окне просмотра браузера, или, как в моем случае, может быть случайный элемент, охватывающий объект. Предположим, у нас есть веб-приложение, в котором пользователь может поместить окно. –

+1

Метод выше не полагается на то, что он находится в окне просмотра браузера. –

1

Если путь является выпуклым, мы можем сделать это в просто так:

Raphael.el.getRandomPointInsideConvex=function(){ 
    if(this.type!='path') return undefined; 

    //sample two points along the path 
    var len=this.getTotalLength(), 
     p1=this.getPointAtLength(Math.random()*len), 
     p2=this.getPointAtLength(Math.random()*len), 
     ratio=Math.random(); 

    //get the random point 
    var x=p1.x+(p2.x-p1.x)*ratio, 
     y=p1.y+(p2.y-p1.y)*ratio; 

    return {x:x,y:y}; 
}; 

Вы можете вызвать метод следующим образ:

//el is an element 
var r=el.getRandomPointInsideConvex(); 
//draw a cross at this point to show it. 
el.paper.path(['M',r.x-2,r.y,'L',r.x+2,y,'M',r.x,r.y-2,'L',r.x,r.y+2]); 

Надеется, что это помогает.

+0

Хорошая идея. Для будущих читателей я хочу предупредить вас, что эти решения не дают равномерного выбора. Это означает, что точки из определенных областей имеют более высокую вероятность выбора. –

+0

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