Canvas画椭圆的方法

May 17, 2016 am 09:07 AM

  虽然标题是画椭圆,但是我们先来说说Canvas中的圆

  相信大家对于Canvas画圆都不陌生

oGC.arc(400, 300, 100, 0, 2*Math.PI, false);
复制代码
ログイン後にコピー


  如上所示,直接调用API就可以了,但是计算机内部却是使用光栅学,利用bresenham算法画圆的,这个我们放到最后来说,先说说利用圆的参数方程画圆

circle(oGC, 400, 300, 100);
function circle(context, x, y, a) { // x,y是坐标;a是半径
    var r = 1/a; // ①注意:此处r可以写死,不过不同情况下写死的值不同
    context.beginPath();
    context.moveTo(x + a, y);
    for(var i = 0; i < 2 * Math.PI; i += r) {
        context.lineTo(x + a * Math.cos(i), y + a * Math.sin(i));
    }
    context.closePath();
    context.fill();
}
复制代码
ログイン後にコピー


  原理是什么,相信三角函数不错的童鞋理解起来很容易的,如果不知道的话,注意注释①,我变化一下r的值,相信就立竿见影了~

1073.png


1074.png


1075.png


1076.png


  r和2*Math.PI配合就是圆的精细程度,在半径为100的时候,r取1/10就可以了,通用的话可以写死,写成r = 1 / a;这样无论半径取大或者小,圆都会很精细,但是性能会有很大影响

  现在来看看文章的主角,针对圆来看椭圆的

function EllipseOne(context, x, y, a, b) {
    var step = (a > b) ? 1 / a : 1 / b;
    context.beginPath();
    context.moveTo(x + a, y);
    for(var i = 0; i < 2 * Math.PI; i += step) {
        context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i));
    }
    context.closePath();
    context.fill();
}
复制代码
ログイン後にコピー


  和圆基本一样,不过圆只有一个半径,而椭圆分为长轴和短轴了。

  看下效果~

1077.png


  好了,画椭圆成功,文章结束~

  怎么可能!

  就这样结束也太没品了,刚刚是方法一,下面来看其他的

  方法二,均匀压缩法

  这是我最喜欢的方法,易理解,相比较方法一,性能也快了很多,先贴代码~

  1. function EllipseTwo(context, x, y, a, b) {
        context.save();
        var r = (a > b) ? a : b;
        var ratioX = a / r;
        var ratioY = b / r;
        context.scale(ratioX, ratioY);
        context.beginPath();
        context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false);
        context.closePath();
        context.restore();
        context.fill();
    }
    ログイン後にコピー
复制代码


  原理是利用了scale来对一个标准的圆进行压缩,ratioX是横轴缩放比率,ratioY是纵轴缩放比率,就因为这两个值不同,使得将标准圆缩放成了一个椭圆

  记得save()和restore()还原context环境,so easy理解的方法

  下面两种方法很高大上,都是利用三次贝塞尔曲线法

  方法三,四,贝塞尔法

function EllipseThree(context, x, y, a, b) {
    var ox = 0.5 * a,
        oy = 0.6 * b;
    context.save();
    context.translate(x, y);
    context.beginPath();
    context.moveTo(0, b);
    context.bezierCurveTo(ox, b, a, oy, a, 0);
    context.bezierCurveTo(a, -oy, ox, -b, 0, -b);
    context.bezierCurveTo(-ox, -b, -a, -oy, -a, 0);
    context.bezierCurveTo(-a, oy, -ox, b, 0, b);
    context.closePath();
    context.fill();
    context.restore();
}
function EllipseFour(context, x, y, a, b) {
    var k = 0.5522848,
    ox = k * a,
    oy = k * b;
    context.translate(x, y);
    context.beginPath();
    context.moveTo(-a, 0);
    context.bezierCurveTo(-a, oy, -ox, -b, 0, -b);
    context.bezierCurveTo(ox, -b, a, -oy, a, 0);
    context.bezierCurveTo(a, oy, ox, b, 0, b);
    context.bezierCurveTo(-ox, b, -a, oy, -a, 0);
    context.closePath();
    context.fill();
}
复制代码
ログイン後にコピー
  贝塞尔法的核心在于两个控制点的选取,但是它有致命的问题,当lineWidth较宽的时候,椭圆较扁,长轴较尖锐,会出现不平滑的情况

  如果不知道什么事贝塞尔的话就自行百度……这个不解释了……

  后面还有最后一种光栅法画椭圆,光栅法画圆很简单,画椭圆挺麻烦的,下面是最简单的一种椭圆画法,等于是lineWidth为1px的情况下
function EllipseFive(context, x, y, a, b) {
    var data = context.getImageData(0, 0, 800, 600);
    var imageData = data.data;
    var tx = 0;
    var ty = b;
    var d = b*b + a*a*(-b + 0.25);
    var mx = a * a / Math.sqrt(a * a + b * b);
    while(tx <= mx) {
        if(d < 0) {
            d += b * b * (2 * tx + 3);
        } else {
            ty--;
            d += b * b * (2 * tx + 3) + 2 * a * a * (1 - ty);
            
        }
        tx++;
        setPix(x + tx, y + ty);
        setPix(x + tx, y - ty);
        setPix(x - tx, y + ty);
        setPix(x - tx, y - ty);
    }
    d = b * b * (tx + 0.5) * (tx + 0.5) + a * a * (ty - 1) * (ty - 1) - a * a * b * b;
    while (ty > 0) {
        if (d < 0) {
            tx++;
            d += b*b*(2 * tx + 2) + a*a*(-2 * ty + 3);
        }
        else {
            d += a*a*(-2 * ty + 3);
        }
        ty--;
        setPix(x + tx, y + ty);
        setPix(x - tx, y + ty);
        setPix(x + tx, y - ty);
        setPix(x - tx, y - ty);
    }
    context.putImageData(data, 0, 0);
    function setPix(x, y){
        console.log(x, y);
        var index = getStartIndex(x, y);
        for(var i = 0; i< 4; i++) {
            if(i == 3) {
                imageData[index + i] = 255;
            }
            else{
                imageData[index + i] = 128;
            }
        }
    }
    function getStartIndex(x, y) {
        return y * 800 * 4 + x * 4;
    }
}
复制代码
ログイン後にコピー


  给个结果图~

1078.png


  光栅法的原理在这里就不说啦,那个说的话篇幅很大,在这里也不推荐用光栅法去画椭圆,针对不同线宽很麻烦

  ok这篇文章就到这啦,Thanks~

以上就是Canvas画椭圆的方法的内容,更多相关内容请关注PHP中文网(www.php.cn)!


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

キャンバスを使用している学校はどこですか? キャンバスを使用している学校はどこですか? Aug 18, 2023 pm 05:59 PM

Canvas を使用している学校には、スタンフォード大学、MIT、コロンビア大学、カリフォルニア大学バークレー校などが含まれます。詳細な紹介: 1. スタンフォード大学は、主要なオンライン学習プラットフォームとして Canvas を使用しています。スタンフォード大学の教師と学生は、Canvas を使用してコースの内容を管理および伝達し、オンライン ディスカッション、課題の提出、試験などの機能を通じて学習します。2. マ州Polytechnic Institute と MIT もオンライン学習管理システムとして Canvas を使用しており、Canvas プラットフォームを通じてコース管理を行っています。3. コロンビア大学など。

キャンバス矢印プラグインとは何ですか? キャンバス矢印プラグインとは何ですか? Aug 21, 2023 pm 02:14 PM

キャンバス矢印プラグインには、1. シンプルで使いやすい API を備え、カスタムの矢印効果を作成できる Fabric.js、2. 矢印を描画する機能を提供し、さまざまな矢印を作成できる Konva.js が含まれます。スタイル; 3. 豊富なグラフィックス処理機能を提供し、さまざまな矢印効果を実現できる Pixi.js; 4. 矢印のスタイルやアニメーションを簡単に作成および制御できる Two.js; 5. さまざまな矢印効果を作成できる Arrow.js ; 6. 大まかな.jsでは、手描きの矢印などが作成できます。

キャンバスクロックの詳細は何ですか? キャンバスクロックの詳細は何ですか? Aug 21, 2023 pm 05:07 PM

キャンバス時計の詳細には、時計の外観、目盛り、デジタル時計、時針、分針、秒針、中心点、アニメーション効果、その他のスタイルなどが含まれます。詳細な紹介: 1. 時計の外観、キャンバスを使用して時計の外観として円形の文字盤を描画し、文字盤のサイズ、色、境界線などのスタイルを設定できます; 2. 目盛り線、目盛り線を描画します。位置; 3. デジタル時計、現在の時と分を示すために文字盤にデジタル時計を描くことができます; 4. 時針、分針、秒針など。

キャンバス フレームワークを学び、一般的に使用されるキャンバス フレームワークについて詳しく説明します キャンバス フレームワークを学び、一般的に使用されるキャンバス フレームワークについて詳しく説明します Jan 17, 2024 am 11:03 AM

Canvas フレームワークを探索する: 一般的に使用される Canvas フレームワークを理解するには、特定のコード例が必要です。 はじめに: Canvas は HTML5 で提供される描画 API であり、これを通じて豊富なグラフィックスやアニメーション効果を実現できます。描画の効率と利便性を向上させるために、多くの開発者がさまざまな Canvas フレームワークを開発しました。この記事では、一般的に使用される Canvas フレームワークをいくつか紹介し、読者がこれらのフレームワークの使用方法をより深く理解できるように、具体的なコード例を示します。 1.EaselJSフレームワークEa

html2canvas にはどのようなバージョンがありますか? html2canvas にはどのようなバージョンがありますか? Aug 22, 2023 pm 05:58 PM

html2canvas のバージョンには、html2canvas v0.x、html2canvas v1.x などが含まれます。詳細な紹介: 1. html2canvas v0.x (html2canvas の初期バージョン) 最新の安定バージョンは v0.5.0-alpha1 です。これは、多くのプロジェクトで広く使用され、検証されている成熟したバージョンです。2. html2canvas v1.x、これは html2canvas の新しいバージョンです。

uniapp は、キャンバスを使用してチャートやアニメーション効果を描画する方法を実装します。 uniapp は、キャンバスを使用してチャートやアニメーション効果を描画する方法を実装します。 Oct 18, 2023 am 10:42 AM

キャンバスを使用して uniapp でチャートやアニメーション効果を描画する方法には、特定のコード例が必要です。 1. はじめに モバイル デバイスの普及に伴い、モバイル端末上でさまざまなチャートやアニメーション効果を表示する必要があるアプリケーションがますます増えています。 uniapp は、Vue.js に基づくクロスプラットフォーム開発フレームワークとして、キャンバスを使用してチャートやアニメーション効果を描画する機能を提供します。この記事では、uniapp がキャンバスを使用してチャートやアニメーション効果を実現する方法を紹介し、具体的なコード例を示します。 2.キャンバス

tkinter Canvas にはどのようなプロパティがありますか? tkinter Canvas にはどのようなプロパティがありますか? Aug 21, 2023 pm 05:46 PM

tkinter Canvas 属性には、bg、bd、relief、width、height、cursor、highlightbackground、highlightcolor、highlightthickness、insertbackground、insertwidth、selectbackground、selectforeground、xscrollcommand 属性などが含まれます。詳しい紹介

ゲーム開発におけるキャンバスの強力な役割と応用を探る ゲーム開発におけるキャンバスの強力な役割と応用を探る Jan 17, 2024 am 11:00 AM

ゲーム開発におけるキャンバスの力と応用を理解する 概要: インターネット技術の急速な発展に伴い、Web ゲームはプレイヤーの間でますます人気が高まっています。 Web ゲーム開発の重要な部分として、キャンバス テクノロジーがゲーム開発に徐々に登場し、その強力なパワーと応用性を示しています。この記事では、ゲーム開発におけるキャンバスの可能性を紹介し、具体的なコード例を通じてその応用例を示します。 1. Canvas テクノロジの概要 Canvas は HTML5 の新しい要素で、これにより次のことが可能になります。

See all articles