代金香 發表於 2019-12-20 13:47:00

HTML+JavaScript画函数图像

<p><img src="https://img2018.cnblogs.com/blog/1648799/201912/1648799-20191220134837583-1423950026.png"></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;

        &lt;head&gt;
                &lt;meta charset="UTF-8"&gt;
                &lt;title&gt;函数图像绘制工具&lt;/title&gt;
                &lt;script type="text/javascript" src="js/funcImg.js"&gt;&lt;/script&gt;
                &lt;style&gt;
                        #div-img {
                                /* 此决定画布的宽高 */
                                width: 500px;
                                height: 500px;
                        }
                       
                        #input-controller {
                                padding: 10px;
                                background-color: azure;
                        }
                &lt;/style&gt;
        &lt;/head&gt;

        &lt;body&gt;
                &lt;div id="input-controller"&gt;
                        &lt;div id="function"&gt;
                                &lt;button onclick="Add()"&gt;添加函数&lt;/button&gt;
                                &lt;span id="mod" style="display:none" name="0"&gt;
                                        &lt;input type="color"/&gt;y=
                                        &lt;input type="text" value="x^3" name="Fun"/&gt;
                                        &lt;button onclick="Delete(this.parentNode)"&gt;Delete&lt;/button&gt;
                      &lt;input type="checkbox" onclick="reDraw()" checked="checked"/&gt;Draw Line
                                &lt;/span&gt;
                        &lt;/div&gt;

                        &lt;div id="option"&gt;
                                X:&lt;input id="xLeftValue" /&gt; ~
                                &lt;input id="xRightValue" /&gt;
                                &lt;br&gt; Y:
                                &lt;input id="yLeftValue" /&gt; ~
                                &lt;input id="yRightValue" /&gt;
                                &lt;br&gt;

                                &lt;span id="show-size"&gt;Size:&lt;/span&gt;
                        &lt;/div&gt;
                        &lt;button onclick="change()"&gt;画图&lt;/button&gt;
                &lt;/div&gt;
                &lt;div id="main"&gt;

                        &lt;h1&gt;函数图像绘制工具&lt;/h1&gt;
                        &lt;div id="div-img"&gt;
                                &lt;canvas id="graph"&gt;&lt;/canvas&gt;
                        &lt;/div&gt;
                &lt;/div&gt;

        &lt;/body&gt;
        &lt;script&gt;
                const FONT_STYLE = "10px 黑体";
                const MIN = 1e-4;
                const MAX = 1e8;
                const EPS = 1e-12;
                const CANVAS = $("graph");
                const CONTEXT_2D = CANVAS.getContext("2d");
                const FUN_IMG_WIDTH = CANVAS.parentNode.clientWidth;
                const FUN_IMG_HEIGHT = CANVAS.parentNode.clientHeight;
                var xLeftValue = -FUN_IMG_WIDTH / 100; // x最左的值
                var xRightValue = FUN_IMG_WIDTH / 100;
                var yLeftValue = -FUN_IMG_HEIGHT / 100;
                var yRightValue = FUN_IMG_HEIGHT / 100;
                var tableX, tableY, countX, countY;
                var funStage = 0,
                        mouseX, mouseY;
                var tmp;
        &lt;/script&gt;
        &lt;script&gt;
                CANVAS.width = FUN_IMG_WIDTH;
                CANVAS.height = FUN_IMG_HEIGHT;
                $("show-size").innerHTML = "Size:" + FUN_IMG_WIDTH + "*" + FUN_IMG_HEIGHT;

                CANVAS.onmousedown = function(ob) {
                        mouseX = ob.layerX;
                        mouseY = ob.layerY;
                        funStage = 1;
                }
                CANVAS.onmousemove = function(ob) {
                        if(funStage != 1) {
                                return;
                        }
                        var NoX, NoY, det;
                        NoX = ob.layerX;
                        NoY = ob.layerY;
                        det = (mouseX - NoX) / FUN_IMG_WIDTH * (xRightValue - xLeftValue);
                        xLeftValue += det;
                        xRightValue += det;
                        det = (NoY - mouseY) / FUN_IMG_HEIGHT * (yRightValue - yLeftValue);
                        yLeftValue += det;
                        yRightValue += det;
                        mouseX = NoX;
                        mouseY = NoY;
                        reDraw();
                        update();
                }
                CANVAS.onmouseup = function(ob) {
                        if(funStage == 1) {
                                funStage = 0;
                                reDraw();
                        }
                }
                CANVAS.onmouseleave = function(ob) {
                        if(funStage == 1) {
                                funStage = 0;
                                reDraw();
                        }
                }
                CANVAS.onmousewheel = function(ob) {
                        // 取消事件的默认动作
                        ob.preventDefault();
                        // 放大的比例
                        var ScaleRate = 0.9;
                        var detail;
                        if(ob.wheelDelta) {
                                detail = ob.wheelDelta;
                        } else if(ob.detail) {
                                detail = ob.detail;
                        }
                        if(detail &gt; 0) {
                                scale(ob.layerX, FUN_IMG_HEIGHT - 1 - ob.layerY, ScaleRate);
                        } else {
                                scale(ob.layerX, FUN_IMG_HEIGHT - 1 - ob.layerY, 1 / ScaleRate);
                        }
                        reDraw();
                        update();
                }
                // 初始化
                reDraw();
                update();
                Add();
        &lt;/script&gt;

&lt;/html&gt;
</code></pre>
<p>funcImg.js</p>
<pre><code class="language-javascript">function $(id) {
        return document.getElementById(id);
}

function getRandomColor() {
        var color = '#' + ('00000' + (Math.random() * 0x1000000 &lt;&lt; 0).toString(16)).substr(-6);
        return color;
}

function FunWork(f, x) {
        switch(f) {
                case "":
                        {
                                return x;
                                break;
                        }
                case "sin":
                        {
                                return Math.sin(x);
                                break;
                        }
                case "cos":
                        {
                                return Math.cos(x);
                                break;
                        }
                case "tan":
                        {
                                return Math.tan(x);
                                break;
                        }
                case "abs":
                        {
                                return Math.abs(x);
                                break;
                        }
                case "sqrt":
                        {
                                return Math.sqrt(x);
                                break;
                        }
                case "ln":
                        {
                                return Math.log(x);
                                break;
                        }
                case "log":
                        {
                                return Math.log(x) / Math.LN2;
                                break;
                        } //2为底
                case "lg":
                        {
                                return Math.log(x) / Math.LN10;
                                break;
                        } //10为底
                case "floor":
                        {
                                return Math.floor(x);
                                break;
                        }
                case "ceil":
                        {
                                return Math.ceil(x);
                                break;
                        }
                case "int":
                        {
                                return parseInt(x);
                                break;
                        }
                default:
                        {
                                return NaN;
                                break;
                        }
        }
}

function ChangeToPointY(y) {
        return FUN_IMG_HEIGHT - 1 - parseInt((y - yLeftValue) / (yRightValue - yLeftValue) * FUN_IMG_HEIGHT);
}

function isChar(c) {
        return(c &gt;= 'a' &amp;&amp; c &lt;= 'z') || (c &gt;= 'A' &amp;&amp; c &lt;= 'Z');
}

function isDigit(c) {
        return c &gt;= '0' &amp;&amp; c &lt;= '9';
}

function priority(c) {
        switch(c) {
                case '(':
                        return 0;
                        break;
                case '+':
                        return 1;
                        break;
                case '-':
                        return 1;
                        break;
                case '*':
                        return 2;
                        break;
                case '/':
                        return 2;
                        break;
                case '^':
                        return 3;
                        break;
                default:
                        return -1;
                        break;
        }
}
// 是运算符
function isOpt(c) {
        return priority(c) != -1;
}

function singleCalc(c, a, b) {
        if(c == '+') {
                return a + b;
        } else
        if(c == '-') {
                return a - b;
        } else
        if(c == '*') {
                return a * b;
        } else
        if(c == '/') {
                return a / b;
        } else
        if(c == '^') {
                return Math.pow(a, b);
        } else {
                return NaN;
        }
}

function getTable() {
        tmp = (xRightValue - xLeftValue + EPS) / 20;

        tableX = 1;
        countX = 0;
        countY = 0;
        while(tableX &lt; tmp) {
                tableX *= 10;
        }
        while(tableX / 10 &gt; tmp) {
                tableX /= 10;
                countX++;
        }
        if(tableX &gt;= 1) {
                countX = 0;
        }
        if(tableX / 5 &gt; tmp) {
                tableX /= 5;
                countX++;
        } else if(tableX / 2 &gt; tmp) {
                tableX /= 2;
                countX++;
        }
        var i = parseInt(xLeftValue / tableX) + (xLeftValue &gt; 0)
        for(; i * tableX &lt; xRightValue; i++) {
                if(i == 0) {
                        // y轴
                        CONTEXT_2D.fillStyle = "black";
                } else {
                        // 普通竖线
                        CONTEXT_2D.fillStyle = "#CDB7B5";
                }
                tmp = (i * tableX - xLeftValue) / (xRightValue - xLeftValue) * FUN_IMG_WIDTH;
                var _width = 1;
                var _height = FUN_IMG_HEIGHT;
                CONTEXT_2D.fillRect(tmp, 0, _width, _height);
                // 竖线上的数字
                CONTEXT_2D.fillStyle = "red";
                CONTEXT_2D.font = FONT_STYLE;
                var _text = (i * tableX).toFixed(countX);
                var _x = tmp + 2;
                var _y = 10;
                CONTEXT_2D.fillText(_text, _x, _y);
        }
        tmp = (yRightValue - yLeftValue + EPS) / 20;
        tableY = 1;

        while(tableY &lt; tmp) {
                tableY *= 10;
        }
        while(tableY / 10 &gt; tmp) {
                tableY /= 10, countY++;
        }
        if(tableY / 5 &gt; tmp) {
                tableY /= 5, countY++;
        } else if(tableY / 2 &gt; tmp) {
                tableY /= 2, countY++;
        }
        if(tableY &gt;= 1) {
                countY = 0;
        }
        var i = parseInt(yLeftValue / tableY) + (yLeftValue &gt; 0);
        for(; i * tableY &lt; yRightValue; i++) {
                // 横线
                if(i == 0) {
                        // x轴
                        CONTEXT_2D.fillStyle = "black";
                } else {
                        // 普通横线
                        CONTEXT_2D.fillStyle = "#CDB7B5";
                }
                tmp = (i * tableY - yLeftValue) / (yRightValue - yLeftValue) * FUN_IMG_HEIGHT;
                CONTEXT_2D.fillRect(0, FUN_IMG_HEIGHT - 1 - tmp, FUN_IMG_WIDTH, 1);
                // 横线上的数字
                CONTEXT_2D.fillStyle = "blue";
                CONTEXT_2D.font = FONT_STYLE;
                CONTEXT_2D.fillText((i * tableY).toFixed(countY), 0, FUN_IMG_HEIGHT - 1 - tmp);
        }
}

function drawArc(x, y) {
        CONTEXT_2D.beginPath();
        // arc(弧形),画圆
        CONTEXT_2D.arc(x, y, 1, 0, Math.PI * 2);
        CONTEXT_2D.closePath();
        CONTEXT_2D.fill();
}

function drawLine(lx, ly, px, py) {
        CONTEXT_2D.beginPath();
        CONTEXT_2D.moveTo(lx, ly);
        CONTEXT_2D.lineTo(px, py);
        CONTEXT_2D.closePath();
        CONTEXT_2D.stroke(); // 绘制
}

function reDraw() {
        CONTEXT_2D.clearRect(0, 0, FUN_IMG_WIDTH, FUN_IMG_HEIGHT);
        getTable();
        getFunction();
}

function change() {
        xLeftValue = parseFloat($("xLeftValue").value);
        xRightValue = parseFloat($("xRightValue").value);
        yLeftValue = parseFloat($("yLeftValue").value);
        yRightValue = parseFloat($("yRightValue").value);
        reDraw();
}

function update() {
        $("xLeftValue").value = xLeftValue;
        $("xRightValue").value = xRightValue;
        $("yLeftValue").value = yLeftValue;
        $("yRightValue").value = yRightValue;
}

function scale(x, y, times) {
        if(x &lt; 0 || x &gt;= FUN_IMG_WIDTH || y &lt; 0 || y &gt;= FUN_IMG_HEIGHT) return;

        if(times &lt; 1 &amp;&amp; (xRightValue - xLeftValue &lt; MIN || yRightValue - yLeftValue &lt; MIN)) {
                return;
        }
        if(times &gt; 1 &amp;&amp; (xRightValue - xLeftValue &gt; MAX || yRightValue - yLeftValue &gt; MAX)) {
                return;
        }

        x = xLeftValue + (xRightValue - xLeftValue) / FUN_IMG_WIDTH * x;
        y = yLeftValue + (yRightValue - yLeftValue) / FUN_IMG_HEIGHT * y;
        xLeftValue = x - (x - xLeftValue) * times;
        xRightValue = x + (xRightValue - x) * times;
        yLeftValue = y - (y - yLeftValue) * times;
        yRightValue = y + (yRightValue - y) * times;
}

function Calc(fun, X, Value) {
        var number = new Array(),
                opt = new Array(),
                F = new Array(),
                now = 0,
                f = "",
                tmp, a, b, sign = 1,
                base = 0,
                j;
        for(var i = 0; i &lt; fun.length; i++) {
                for(j = 0; j &lt; X.length; j++)
                        if(X == fun) {
                                if(i == 0 || isOpt(fun)) now = Value;
                                else now *= Value;
                                break;
                        }
                if(j == X.length)
                        if(fun == '(') F.push(f), f = "", opt.push('(');
                        else
                if(fun == ')') {
                        number.push(now * sign);
                        now = 0;
                        sign = 1;
                        base = 0;
                        while((tmp = opt.pop()) != '(') {
                                b = number.pop();
                                a = number.pop();
                                tmp = singleCalc(tmp, a, b);
                                number.push(tmp);
                        }
                        now = FunWork(F.pop(), number.pop());
                } else
                if(fun == '.') base = 1;
                else
                if(fun == '+' &amp;&amp; (i == 0 || priority(fun) != -1));
                else
                if(fun == '-' &amp;&amp; (i == 0 || priority(fun) != -1)) sign = -1;
                else
                if(fun == 'e')
                        if(i == 0 || isOpt(fun)) now = Math.E;
                        else now *= Math.E;
                else
                if(fun == 'p' &amp;&amp; fun == 'i') {
                        if(i == 0 || isOpt(fun)) now = Math.PI;
                        else now *= Math.PI;
                        i += 1;
                } else
                if(isDigit(fun))
                        if(base == 0) now = now * 10 + (fun - '0');
                        else base /= 10, now += base * (fun - '0');
                else
                if(isChar(fun)) f += fun;
                else if(isOpt(fun)) {
                        number.push(now * sign);
                        now = 0;
                        sign = 1;
                        base = 0;
                        var s = priority(fun);
                        if(s == -1) return 0;
                        while(s &lt;= priority(opt)) {
                                b = number.pop();
                                a = number.pop();
                                tmp = singleCalc(opt.pop(), a, b);
                                number.push(tmp);
                        }
                        opt.push(fun);
                }
        }
        number.push(now * sign);
        while(opt.length &gt; 0) {
                b = number.pop();
                a = number.pop();
                tmp = singleCalc(opt.pop(), a, b);
                number.push(tmp);
        }
        return number.pop();
}

function getFunction() {
        // group:函数(可能是复数)
        var group = document.getElementsByName("Fun");
        var x, y;
        var lax, lay;
        var px, py
        var color, outSide, type
        var ValueL, ValueR, ValueS, isDrawLine, tmp, TMP;

        for(var k = 1; k &lt; group.length; k++) {

                var _funcItem = group.parentNode;

                outSide = 1;
                //type = _funcItem.children.value;
                // 颜色
                color = _funcItem.children.value;
                // 函数表达式
                funcExpression = group.value;
                // 是否画线(默认画点)
                isDrawLine = _funcItem.children.checked;

                CONTEXT_2D.fillStyle = CONTEXT_2D.strokeStyle = color;

                for(var i = 0; i &lt; FUN_IMG_WIDTH; i++) {
                        x = xLeftValue + (xRightValue - xLeftValue) / FUN_IMG_WIDTH * i;
                        y = Calc(funcExpression, ['x'], );
                        if(isNaN(y)) {
                                continue;
                        }
                        px = i;
                        py = ChangeToPointY(y);
                        if(y &gt;= yLeftValue &amp;&amp; y &lt; yRightValue) {
                                // 画圆
                                drawArc(px, py);
                                if(isDrawLine) {
                                        drawLine(lax, lay, px, py);
                                }
                                outSide = 0;
                        } else {
                                if(isDrawLine) {
                                        if(!outSide) {
                                                drawLine(lax, lay, px, py);
                                        }
                                } else {}
                                outSide = 1;
                        }
                        lax = px;
                        lay = py;
                }
        }
}

function Add() {
        var newInput = $("mod").cloneNode(true);
        newInput.style.display = "block";
        newInput.children.value = getRandomColor();
        $("function").appendChild(newInput);
}

function Delete(node) {
        node.parentNode.removeChild(node);
}
</code></pre><br><br>
来源:https://www.cnblogs.com/tigerlion/p/12072713.html
頁: [1]
查看完整版本: HTML+JavaScript画函数图像