في القماش ، يمكنك بسهولة رسم دائرة باستخدام طريقة ARC. في الأصل ، يمكن أيضًا اعتبار الدائرة من القطع الناقص ذات العرض والارتفاع المتساوي ، ولكن لا توجد طريقة لرسم القطع الناقص في قماش. نحن بحاجة إلى استخدام طرق أخرى لمحاكاة ذلك.
بادئ ذي بدء ، نحتاج إلى توضيح المعلمات المطلوبة لرسم القطع الناقص. تخبرنا المعرفة الهندسية الأساسية أن القطع الناقص يحتاج إلى إحداثيات المركزية أو العرض أو الطول أو زاوية الدوران ، ولكن يمكن تجنب ذلك في الوقت الحالي ، يكون الدوران سهلًا نسبيًا.
1. استخدم Lineto لرسم القطع الناقص لقد قرأت ذلك بشكل صحيح ، Lineto ، وهي طريقة تستخدم بحتة لرسم خطوط مستقيمة ، يمكن استخدامها بالفعل لرسم علامات القطع! ؟ لكنه موجود ، لكن أسلوب الكتابة لا يصدق حقًا:دالة drawellipse (قماش ، O ، الزراعة العضوية ، OB) {
// ارسم القطع الناقص ، مثال: var b = صفيف جديد (150،150) ؛ DrawelliPse (HB ، B ، 50،30) ؛
مع (قماش) {
var x = o [0]+OA ؛
var y = o [1] ؛
Moveto (x ، y) ؛
لـ (var i = 0 ؛ i <= 360 ؛ i ++) {
var ii = i*math.pi/180 ؛
var x = o [0]+oa*math.cos (ii) ؛
var y = o [1] -ob*math.sin (ii) ؛
Lineto (x ، y) ؛
}
}
}
مبدأ هذه الطريقة هو أن الدائرة لديها 360 درجة ، لذلك استخدم lineto للحلق 360 مرة ، ورسم شرائح الخط في كل درجة ، وأخيراً توصيلها بمسائل. من بينها ، يجب استخدام وظيفة جيب التجربة المثلثية لحساب.
لاحظ أن المعلمة الثانية لهذه الطريقة هي صفيف ، أي إحداثيات المركز للقطع الناقص.
الفكرة غريبة للغاية ، والقطع الناقص المرسومة ناعمة نسبيا. ولكن لا يستحق استخدام - هذه الطريقة تتطلب 360 دورة لكل القطع الناقص المرسومة. فقط عندما يتم رسم القطع الناقص هو أدنى اختبار لأداء المتصفح.
نحن فقط بحاجة إلى فهم أفكاره
2. استخدم القوس لرسم دائرة وتوسيع نطاقه في القطع الناقص النص الأصلي لهذه الطريقة هنا ، والوظيفة الأساسية هي كما يلي:var canvas = document.getElementById ('mycanvas') ؛
var context = canvas.getContext ('2d') ؛
var centerx = 0 ؛
var centery = 0 ؛
VAR RADIUS = 50 ؛
// Save State
context.save () ؛
// ترجمة السياق
context.translate (canvas.width / 2 ، canvas.height / 2) ؛
// Scale Context بشكل أفقي
context.scale (2 ، 1) ؛
// ارسم الدائرة التي سيتم تمديدها إلى بيضاوي
context.beginPath () ؛
Context.Arc (CenterX ، Centery ، Radius ، 0 ، 2 * Math.pi ، false) ؛
// استعادة إلى الحالة الأصلية
context.restore ()
تستخدم هذه الطريقة وظيفة قماش لم أذكرها من قبل ، أي المقياس ، والذي يمكن أن يدرك تحجيم القماش. القياس له اتجاهان: أفقي ورأسي. يوسع الكود الاتجاه الأفقي للقماش ، بينما يظل الاتجاه العمودي دون تغيير. لذلك ، تتحول الدائرة المرسومة بواسطة قوس إلى القطع الناقص.
هذه الطريقة رائعة للغاية للوهلة الأولى ، مع عدد قليل من الرموز ، والمبادئ بسيطة وسهلة الفهم. ولكن بعد تحليله ، ستجد أوجه القصور الواضحة ، أي أنها - غير دقيقة! على سبيل المثال ، أحتاج إلى القطع الناقص التي يبلغ ارتفاعها 171 و 56. إذا قمنا بتعيين نصف قطر القوس إلى 28 ، فسيتم الاكتئاب العدد اللاحق من 171/28/2.
ومع ذلك ، هناك طريقة حل وسط لضبط نصف قطر القوس إلى 100 ، وبعد ذلك ، إذا لم يكن كافيًا ، فسيتم توسيعه ، وإذا تجاوزه ، فسيتم تقليله. ومع ذلك ، لا يزال غير دقيق.
3. استخدم Bezier Curveto نظرًا لأنني شعرت أن طريقة التحجيم أعلاه غير دقيقة ، فأنا أريد حقًا العثور على طريقة دقيقة لرسم القطرات ، وأخيراً وجدتها على Stackoverflow:دالة drawellipse (CTX ، X ، Y ، W ، H) {
var kappa = 0.5522848 ؛
OX = (W / 2) * Kappa ، // Control Point Offset أفقي
OY = (H / 2) * Kappa ، // التحكم في نقطة الإزاحة العمودية
xe = x + w ، // x-end
ye = y + h ، // y-end
xm = x + w / 2 ، // x-middle
ym = y + h / 2 ؛ // y-middle
ctx.beginpath () ؛
ctx.moveto (x ، ym) ؛
ctx.beziercurveto (x ، ym - oy ، xm - ox ، y ، xm ، y) ؛
ctx.beziercurveto (xm + ox ، y ، xe ، ym - oy ، xe ، ym) ؛
ctx.beziercurveto (xe ، ym + oy ، xm + ox ، ye ، xm ، ye) ؛
ctx.beziercurveto (xm - ox ، ye ، x ، ym + oy ، x ، ym) ؛
ctx.closepath () ؛
ctx.stroke () ؛
}
يمكن اعتبار هذه الطريقة مثالية. قام بتقسيم القطع الناقص إلى 4 منحنيات بيزير وربطها بإخضاع. العرض النهائي والارتفاع دقيقان نسبيا والنفقات العامة أقل.
لكن هذه الطريقة لا تزال لديها عيوبها. ينظر الجميع إلى معلمة Kappa ، وهناك قيمة غريبة للغاية. أعتقد أن الكثير من الناس لا يفهمون سبب اضطرارهم إلى أخذ هذه القيمة قبل أن يخبرك خبير الهندسة لماذا يرغبون في أخذ هذه القيمة - ما زلت لا أعرف ذلك. وكان لدي رغبة قوية في تغييره ومعرفة ما هي العواقب.
بالطبع ، لا يمكن القول إن دافعي المشابه لمرضى الوسواس القهري هو عيب هذه الطريقة. عيبه الحقيقي هو - لماذا تحتاج إلى استخدام 4 منحنيات Bezier؟ أنا شخصياً أعتقد أن القطع الناقص يتكون من منحنيين بيزييه بدلاً من أربعة. قادتني هذه الفكرة في النهاية إلى إيجاد الطريقة الأكثر مثالية لرسم القطع الناقص.
4. استخدم منحنيان بيسل لرسم القطع الناقص
من أجل فهم ما إذا كان يمكن تبسيط الطريقة السابقة ، قمت بتسجيل حساب Stackoverflow خصيصًا لطرح الأسئلة. نظرًا لوجود صور في السؤال ، لا يمكن إرسال النقاط. اضطررت إلى استخدام الكفاءة في اللغة الإنجليزية بالكاد للإجابة على أسئلة الأجانب لكسب النقاط. ولكن في النهاية ، جاء حظ سعيد ، وأجيبت الإجابة على سؤال حل مشكلة النقاط الخاصة بي.
لقد أثارت مشكلة العلاقة بين منحنى Besel و Ellipse.
لكي أكون صادقًا ، لم أفهم معظم إجابات الأجانب أدناه ، لكن لحسن الحظ قدم صفحة عينة رمز ، مما جعلني أفهم المبدأ ، وأود أن أشكره مرة أخرى. وفقا لإجابته ، فإن الطريقة التي وجدتها لرسم الحوادث هي كما يلي:
// OVAL
canvasrenderingcontext2d.prototype.oval = وظيفة (x ، y ، العرض ، الارتفاع) {
var k = (العرض/0.75)/2 ،
W = العرض/2 ،
H = الارتفاع/2 ؛
this.beginpath () ؛
this.moveto (x ، yh) ؛
this.beziercurveto (x+k ، yh ، x+k ، y+h ، x ، y+h) ؛
this.beziercurveto (xk ، y+h ، xk ، yh ، x ، yh) ؛
this.closepath () ؛
إرجاع هذا ؛
}
هذه الطريقة دقيقة على حد سواء ولها رمز صغير ، وليس هناك غريب ويصعب فهمه. فقط تذكر ذلك ، نسبة الإحداثيات لعرض القطع الناقص إلى نقطة التحكم في منحنى Besel الذي يرسم القطع الناقص كما يلي:
نقطة التحكم Bessel X = (عرض القطع الناقص/0.75)/2 ينعكس بالفعل في الكود.
يمكنك اختبار الطرق الأربع المذكورة أعلاه لرسم القطع الناقص.
إذا وجدت طريقة أسهل ، فيرجى مشاركتها ومناقشتها.