2013-10-09 17 views
12

我正在收集一些項目的信息,這些信息必須在幾周內開始。 該項目包含一個基於瀏覽器的繪圖工具,用戶可以自行添加預定義的形狀或形成圖形。形狀必須是可選擇的,可以隨意使用類似Illustrator的變形工具(手柄)進行縮放和旋轉。 我們想到的預定義形狀是:矩形,橢圓,半橢圓和(等腰三角形)三角形。將圓角應用於路徑/多邊形

到目前爲止,爲了達到這個目的,我想到了RaphaelJS或FabricJS,但是......每一個形狀(多邊形/路徑)都必須用特定的角點繪製。並且在縮放時角錐必須保持不變,所以不會發生扭曲。用戶可以通過輸入指定舍入。

有幾個障礙/問題:

  • 有一些統一mathemetical公式爲cornerradius適用於我所提到的形狀?或者是否必須將每個形狀都視爲一個小型項目本身?我想將它作爲路徑或多邊形返回,因此可以使用SVG或畫布進行繪製。
  • 通過拖動變形手柄,每個縮放或旋轉操作都將導致(大量)計算來檢索我認爲更新的形狀。矩形是最容易實現的,除橢圓之外,所有其他形狀將更難以計算。有什麼方法可以加快這個過程?

我發現了一個網站,用戶可以繪製流程圖並在幾乎所有形狀上應用角部輻射。它運行的很順利,我不能指出他們是如何做到的。 鏈接:https://www.lucidchart.com/(嘗試按鈕)

現在,我有點無知,我猜平庸在數學。也許有人能把我推向正確的方向並分享一些經驗?

在此先感謝。

順便說一句。性能是這個項目的關鍵。圖形的輸出必須是SVG格式。

回答

1

起點可能是using-svg-curves-to-imitate-rounded-corners。原則是用相對立方(s)的速記轉換每個角落。這個例子非常基本,只適用於兩種可能的情況。

我認爲擴大這個像角落替換速記相對立方體可能擴大到覆蓋其他路徑段。每個段都有一個曲線上的座標點,必須用s段替換。數學可能是這個解決方案中有趣的部分。

27

我結束了一個類似的問題,但無法找到一個簡單的解決方案。我最終寫了一個基於Adobe Illustrator操作的相當通用的圓角函數。它使用貝塞爾曲線而不是弧線,但我認爲結果相當不錯。

它支持在SVG圖像的座標空間中給定半徑的圓整或作爲角與其鄰居之間距離的一部分。

要使用此操作,請包含舍入。JS在你的項目,並調用該函數:

roundPathCorners(pathString, radius, useFractionalRadius) 

的代碼和一些測試路徑在這裏:http://embed.plnkr.co/kGnGGyoOCKil02k04snu/preview

這是從Plnkr例子如何渲染:

SVG Path Rounding Examples

1

儘管這個問題已經有一段時間了,有些人可能會停下來試試這個解決方案:

var BORDER_RADIUS = 20; 

function roundedPath(/* x1, y1, x2, y2, ..., xN, yN */){ 
    context.beginPath(); 
    if (!arguments.length) return; 

    //compute the middle of the first line as start-stop-point: 
    var deltaY = (arguments[3] - arguments[1]); 
    var deltaX = (arguments[2] - arguments[0]); 
    var xPerY = deltaY/deltaX; 
    var startX = arguments[0] + deltaX/2; 
    var startY = arguments[1] + xPerY * deltaX/2; 

    //walk around using arcTo: 
    context.moveTo(startX, startY); 
    var x1, y1, x2, y2; 
    x2 = arguments[2]; 
    y2 = arguments[3]; 
    for (var i = 4; i < arguments.length; i += 2) { 
     x1 = x2; 
     y1 = y2; 
     x2 = arguments[i]; 
     y2 = arguments[i + 1]; 
     context.arcTo(x1, y1, x2, y2, BORDER_RADIUS); 
    } 

    //finally, close the path: 
    context.arcTo(x2, y2, arguments[0], arguments[1], BORDER_RADIUS); 
    context.arcTo(arguments[0], arguments[1], startX, startY, BORDER_RADIUS); 
    context.closePath(); 
} 

訣竅是在第一行中間開始(和停止),然後使用arcTo函數,這個函數描述得非常好here

現在你「只是」必須找到一種方法來將所有形狀表示爲多邊形。

+0

什麼是上下文? –

+0

'context'表示[CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) –