HTML5画布:在滑块移动时绘制曲线

4

嗨,我想在移动滑块时绘制曲线。我有两种曲线类型:贝塞尔曲线和二次曲线。同时,当我绘制曲线时,我希望将一个对象沿着相同的路径移动。我希望它是动态的,所以如果我应该能够更改曲线点。因此,我需要一个函数,可以在滑块变化时调用,就像我对线条所做的那样。以下是我的代码。此代码仅适用于Chrome。

            <!DOCTYPE HTML>
            <html>
                <head>
                    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1">

                    <style type="text/css">
                        .wrapper {
                            margin: 0 auto;
                            width: 1000px;
                        }
                        .canHdr {
                            float: left;
                            width: 450px;
                            height: 400px;
                            border: 1px solid red;
                        }
                    </style>

                </head>
                <body>
                    <form>
                        <!-- wrapper -->
                        <div class="wrapper">

                            <!-- canHdr -->
                            <div id="canHdr" class="canHdr" >

                                <p>
                                    This is my 1st div with quadratic curve I want to draw this curve as I move the slider. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
                                </p>

                                <div class="canOuterHdr" >
                                    <canvas id="myCanvas1" width="300" height="195" style="position: relative;">
                                        [No canvas support]
                                    </canvas>

                                </div>

                                <div id="slider1" class="newBg">
                                    <input id="slide1" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide1');" />
                                </div>

                            </div>
                            <!--/ canHdr -->
                            <!-- canHdr2 -->
                            <div id="canHdr2" class="canHdr" >

                                <p>
                                    This is my 2nd div. I have bezier curve. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
                                </p>

                                <div class="canOuterHdr" >
                                    <canvas id="myCanvas2" width="300" height="195" style="position: relative;">
                                        [No canvas support]
                                    </canvas>

                                </div>

                                <div id="slider2" class="newBg">
                                    <input id="slide2" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide2');" />
                                </div>

                            </div>
                            <!-- canHdr2 -->
                            <!-- canHdr3 -->
                            <div id="canHdr3" class="canHdr" >
                                <p>
                                    This is my 3rd div with slanting line. I want to move a ball on this line when I move the slider. So as the line increases ball will also move on the line.
                                </p>

                                <div class="canOuterHdr" >
                                    <canvas id="myCanvas3" width="300" height="195" style="position: relative;">
                                        [No canvas support]
                                    </canvas>

                                </div>

                                <div id="slider3" class="newBg">
                                    <input id="slide3" type="range" min="0" max="100" step="1" value="0" onchange=" drawSlopeCurve2('slide3','100'); " />
                                </div>

                            </div>
                            <!--/ canHdr3 -->
                            <!-- canHdr4 -->
                            <div id="canHdr4" class="canHdr" >

                                <p>
                                    This is my 4th div with slanting line. I want to move a ball on this line when I move the slider. So as the line increases ball will also move on the line.
                                </p>

                                <div class="canOuterHdr" >
                                    <canvas id="myCanvas4" width="300" height="195" style="position: relative;">
                                        [No canvas support]
                                    </canvas>

                                </div>

                                <div id="slider4" class="newBg">
                                    <input id="slide4" type="range" min="0" max="100" step="1" value="0" onchange=" drawSlopeCurve1('slide4','100'); " />
                                </div>

                            </div>
                            <!--/ canHdr4 -->

                        </div>
                        <!-- /wrapper -->

                        <script type="text/javascript">
                            newSprite('myCanvas3', 16, 170);
                            quadraticCurve('myCanvas1', 18.8, 45, 28, 160, 228, 165);
                            bezierCurve('myCanvas2', 20, 75, 55.2, 150.0, 200,100, 228, 165)
                            function counterSlider(sID) {

                                var slideVal = document.getElementById(sID).value;
                                /*if (maxValue ==100){

                                 slideVal=slideVal/100;
                                 }*/
                                slideVal = slideVal / 100;

                                if (slideVal == 0) {

                                /*  erase('myCanvas2');
                                    erase('myCanvas3');
                                    erase('myCanvas4');*/
                                    //newSprite('myCanvas1b', 18.8, 45);
                                    newSprite('myCanvas3', 16, 170);

                                } else if (slideVal > 0 && slideVal <= 34) {

                                    /*erase('myCanvas1');
                                    //erase('myCanvas1b');
                                    erase('myCanvas2');
                                    erase('myCanvas3');
                                    erase('myCanvas4');*/

                                } else if (slideVal > 34 && slideVal <= 67) {

                                    /*erase('myCanvas1');

                                    erase('myCanvas2');
                                    erase('myCanvas3');
                                    erase('myCanvas4');*/

                                } else if (slideVal > 67 && slideVal <= 100) {

                                    /*erase('myCanvas1');

                                    erase('myCanvas2');
                                    erase('myCanvas3');
                                    erase('myCanvas4');*/

                                }
                            }

                            function erase(canvasId) {

                                var canvas = document.getElementById(canvasId);
                                var context = canvas.getContext("2d");
                                context.beginPath();
                                context.clearRect(0, 0, canvas.width, canvas.height);
                                canvas.width = canvas.width;

                            }

                            /**********for backgroundImage********************/

                            function quadraticCurve(canId, spx, spy, cpx, cpy, endx, endy) {

                                var canvas = document.getElementById(canId);
                                var ctx = canvas.getContext('2d');

                                ctx.beginPath();
                                ctx.moveTo(spx, spy);
                                ctx.quadraticCurveTo(cpx, cpy, endx, endy);
                                ctx.strokeStyle = "#eaca2d";
                                ctx.stroke();

                            }

                            function bezierCurve(canId, spx, spy, cpx1, cpy1, cpx2, cpy2, endx, endy) {

                                var canvas = document.getElementById(canId);
                                var ctx = canvas.getContext('2d');

                                ctx.beginPath();
                                ctx.moveTo(spx, spy);
                                ctx.quadraticCurveTo(cpx1, cpy1, cpx2, cpy2, endx, endy);
                                ctx.strokeStyle = "#eaca2d";
                                ctx.stroke();

                            }

                            function newSprite(canId, mvx, mvy) {
                                var canvas = document.getElementById(canId);
                                var ctx = canvas.getContext('2d');
                                ctx.globalCompositeOperation = 'source-over';
                                //ctx.globalCompositeOperation = "destination-over";
                                ctx.beginPath();
                                ctx.fillStyle = "#0077c1";
                                ctx.arc(mvx, mvy, 6, 0, Math.PI * 2, true);
                                ctx.closePath();
                                ctx.fill();
                            }

                            function drawSlopeCurve1(sID, maxValue) {
                                // erase('canvasTwo');

                                var canId = 'myCanvas4';
                                var slideVal = parseInt(document.getElementById(sID).value);
                                var canvas = document.getElementById(canId);
                                var context = canvas.getContext('2d');
                                canvas.width = canvas.width;
                                //line end points
                                x1 = 16;
                                y1 = 170;
                                x2 = 200;
                                y2 = 80;

                                //get slope (rise over run)
                                var m = (y2 - y1) / (x2 - x1);
                                //get y-intercept
                                var b = y1 - (m * x1);
                                //get distance between the two points
                                var distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
                                //get new x and y values
                                var x = x1 + parseInt(distance / maxValue * slideVal);
                                var y = parseInt(m * x + b);

                                context.beginPath();
                                context.moveTo(x1, y1);
                                context.lineTo(x, y);
                                context.lineWidth = 0.6;
                                context.stroke();

                                newSprite(canId, x, y);
                            }

                            function drawSlopeCurve2(sID, maxValue) {
                                // erase('canvasTwo');

                                var canId = 'myCanvas3';
                                var slideVal = parseInt(document.getElementById(sID).value);
                                var canvas = document.getElementById(canId);
                                var context = canvas.getContext('2d');
                                canvas.width = canvas.width;
                                //line end points
                                x1 = 16;
                                y1 = 170;
                                x2 = 160;
                                y2 = 72;

                                //get slope (rise over run)
                                var m = (y2 - y1) / (x2 - x1);
                                //get y-intercept
                                var b = y1 - (m * x1);
                                //get distance between the two points
                                var distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
                                //get new x and y values
                                var x = x1 + parseInt(distance / maxValue * slideVal);
                                var y = parseInt(m * x + b);

                                context.beginPath();
                                context.moveTo(x1, y1);
                                context.lineTo(x, y);
                                context.lineWidth = 0.6;
                                context.stroke();

                                newSprite(canId, x, y);
                            }

                        </script>
                    </form>
                </body>
            </html>

这是 jsfiddle 的链接:http://jsfiddle.net/QRVxH/


1
你尝试过什么?你已经有绘制曲线的代码了,所以只需要在滑块改变时更改值,你已经编写了滑块值改变的处理程序。 - Sean Airey
1个回答

1
你应该从定义曲线的函数开始,这样你就可以计算每个x位置图形的结束位置。然后你也知道在哪里画出结束点。
我的演示函数有一个在画布上绘制正弦曲线的函数:
function calc(x){
    var y = 100 + ( 50*Math.sin(x*400));
    return y;
}

通过在点之间画一条直线(而不是曲线!)即可获得您的图表。
for (var x=0; x<=400 && (x <= slider.value); x+=3){        
    y= calc(x);
    ctx.lineTo(x, y);
}

工作演示:http://jsfiddle.net/w1ll3m/CbjWK/11/

添加html5slider.js以使滑块在Firefox中正常工作。


非常感谢您的帮助。我已经得到了绘制曲线的代码。但是它的绘制效果不如您的平滑。有人可以帮忙让它更加流畅吗?另外,我想在同一条曲线上移动一个对象。最后一个问题是如何在贝塞尔曲线中实现这个功能。这是我的工作js fiddle链接:http://jsfiddle.net/JGz4T/1/。 - nilesh gadgil
你的代码有多个路径(if/else with point sets),这并不会让它更容易!将你的线定义为方程,比如 y=3x^2 或者 y=cos(x) 这样你可以简单地选定x来计算y。这样你就可以在每4个像素(x轴)的步长上绘制一个点了。http://jsfiddle.net/w1ll3m/JGz4T/4/ 看看我的红色线吧! - Willem
你能解释一下你用来得到这些点的方程吗?另外,我正在尝试将滑块从0位置开始,但它却到了末尾位置。 - nilesh gadgil
这个方程是简单的数学问题,可以参考http://www.mathsisfun.com/data/grapher-equation.html并尝试一些例子。我只是对x取了平方根,并调整函数直到它大致匹配你的线条。我在我的答案中编辑了jsfiddle,并添加了更多的线条作为示例。 - Willem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接