Ответ 1
Это мое предложение искажения перетаскивания (поделиться знаниями, Q & A-style).
Живой пример находится в http://jsfiddle.net/xjHUk/209/, а основной код: (только окно вывода: http://jsfiddle.net/xjHUk/210/embedded/result/)
function transferPoint (xI, yI, source, destination) { var ADDING = 0.001; // to avoid dividing by zero var xA = source[0].x; var yA = source[0].y; var xC = source[2].x; var yC = source[2].y; var xAu = destination[0].x; var yAu = destination[0].y; var xBu = destination[1].x; var yBu = destination[1].y; var xCu = destination[2].x; var yCu = destination[2].y; var xDu = destination[3].x; var yDu = destination[3].y; // Calcultations // if points are the same, have to add a ADDING to avoid dividing by zero if (xBu==xCu) xCu+=ADDING; if (xAu==xDu) xDu+=ADDING; if (xAu==xBu) xBu+=ADDING; if (xDu==xCu) xCu+=ADDING; var kBC = (yBu-yCu)/(xBu-xCu); var kAD = (yAu-yDu)/(xAu-xDu); var kAB = (yAu-yBu)/(xAu-xBu); var kDC = (yDu-yCu)/(xDu-xCu); if (kBC==kAD) kAD+=ADDING; var xE = (kBC*xBu - kAD*xAu + yAu - yBu) / (kBC-kAD); var yE = kBC*(xE - xBu) + yBu; if (kAB==kDC) kDC+=ADDING; var xF = (kAB*xBu - kDC*xCu + yCu - yBu) / (kAB-kDC); var yF = kAB*(xF - xBu) + yBu; if (xE==xF) xF+=ADDING; var kEF = (yE-yF) / (xE-xF); if (kEF==kAB) kAB+=ADDING; var xG = (kEF*xDu - kAB*xAu + yAu - yDu) / (kEF-kAB); var yG = kEF*(xG - xDu) + yDu; if (kEF==kBC) kBC+=ADDING; var xH = (kEF*xDu - kBC*xBu + yBu - yDu) / (kEF-kBC); var yH = kEF*(xH - xDu) + yDu; var rG = (yC-yI)/(yC-yA); var rH = (xI-xA)/(xC-xA); var xJ = (xG-xDu)*rG + xDu; var yJ = (yG-yDu)*rG + yDu; var xK = (xH-xDu)*rH + xDu; var yK = (yH-yDu)*rH + yDu; if (xF==xJ) xJ+=ADDING; if (xE==xK) xK+=ADDING; var kJF = (yF-yJ) / (xF-xJ); //23 var kKE = (yE-yK) / (xE-xK); //12 var xKE; if (kJF==kKE) kKE+=ADDING; var xIu = (kJF*xF - kKE*xE + yE - yF) / (kJF-kKE); var yIu = kJF * (xIu - xJ) + yJ; var b={x:xIu,y:yIu}; b.x=Math.round(b.x); b.y=Math.round(b.y); return b; }
Результат искажен правильно для перспективы (две точки сбрасывания одна). Принцип расчета двухточечной перспективы здесь. script может обрабатывать данные пути SVG, если он удовлетворяет следующим требованиям:
- Все координаты являются абсолютными (что означает заглавные буквы). См. .
- Дуга ( "A" ) не используется
- V и H нормированы на L
Арки могут быть нормализованы, но я еще не нашел пути для кроссбраузеров. V и H в L - это легкая задача, вы должны получить последнюю использованную координату x или y и добавить отсутствующую после L.
Тот же script может обрабатывать также кривые в пути (кривые от Times). Ниже приведен точно такой же код, но атрибут path ( "d" ) отличается:
http://jsfiddle.net/xjHUk/45/ function dummy(a) {return a;}
(Этот код не проверяет недопустимые позиции, как указано выше).
Пути приведенных выше примеров получены из версий SVG Arial и Times. Обратите внимание, что шрифты используют декартова система координат, в которой y-координата увеличивается при движении вверх. В противном случае SVG использует полярную систему координат, которая используется в растровых изображениях и css. Это означает, что при использовании путей из SVG-шрифтов в вышеприведенном коде путь должен быть перевернут по вертикали и масштабирован до нужного размера шрифта. Шрифты TTF (и их SVG-копии) обычно имеют размер 2048, поэтому ограничивающая рамка глифа не имеет масштабирования 2048 px, что обычно слишком велико, когда путь SVG-глифов преобразуется в путь SVG.
Но если вы хотите исказить другие пути SVG, а затем перевернуть и масштабировать ненужные.
Это довольно длинный код (много из-за функции перетаскивания), но я думаю, что тот же эффект может быть достигнут и в каком-то css-3D-преобразовании, но не удача в такой реализации еще...
Для сравнения пример неаспектного искажения (главный конкурент SVG SWF):
http://www.rubenswieringa.com/code/as3/flex/DistortImage/
И для дополнительного сравнения пример расчета VALID перспективы:
http://zehfernando.com/f/TriangleTest.swf