Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Наши скрипты > Графические примитивы.


Автор: magelan 26.9.2011, 11:15
Точка, Линия, Круг. Без всяких канвасов и прочего.
Рисуем цветными дивами.
Большие картины этим не нарисуешь (сожрет много ресурсов), но поставить стрелочку или перечеркнуть часть страницы - реально.

В примере реализованы стрелочные часы.

Код

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>Hello Clock!</title>
<style TYPE="text/css">
        html, body {
          max-width: 100%;
          max-height: 100%;
        }
        .num {
          font-family: serif;
          font-size: 24px;
          color: Gold;
        }

</style>
<script type="text/javascript">
    var Graph = new function()
    {
     this.master = null;
        this.color = 'Black';
        this.size = 1;
        this.preset = function( color, size )
        {
            this.color = color;
            this.size = size;
        }
        this.container = function( master )
        {
            this.master = master;
        }
        this.pixel = function( x, y )
        {
            var el = document.createElement( 'DIV' );
            el.style.position = 'absolute';
            el.style.top = y + 'px';
            el.style.left = x + 'px';
            el.style.backgroundColor = this.color;
            el.style.width = el.style.height = this.size + 'px';
            el.style.fontSize = 0;
            if( this.master == null )
                this.master = document.body;
            this.master.appendChild( el );
        }
        this.line = function( bx, by, ex, ey )
        {
            var dx = ( ex - bx >= 0 )? 1 : -1;
            var dy = ( ey - by >= 0 )? 1 : -1;

            var lengthX = Math.abs( ex - bx );
            var lengthY = Math.abs( ey - by );

            var length = Math.max( lengthX, lengthY );

            var x = bx;
            var y = by;

            if( length == 0 )
                  this.pixel( x, y );

            length++;

            if( lengthY <= lengthX )
            {
                  var d = -lengthX;

                  while( length-- )
                  {
                        this.pixel( x, y );
                        x += dx;
                        d += 2 * lengthY;
                        if( d > 0 )
                        {
                              d -= 2 * lengthX;
                              y += dy;
                        }
                  }
            }
            else
            {
                  var d = -lengthY;

                  while( length-- )
                  {
                        this.pixel( x, y );
                        y += dy;
                        d += 2 * lengthX;
                        if( d > 0 )
                        {
                              d -= 2 * lengthY;
                              x += dx;
                        }
                  }
            }
        }
        this.circle = function ( xc, yc, r )
        {
            var x = 0;
            var y = r;
            var d = 3 - 2 * r;

            while( x <= y )
            {
                this.pixel(  x + xc,  y + yc );
                this.pixel(  x + xc, -y + yc );
                this.pixel( -x + xc, -y + yc );
                this.pixel( -x + xc,  y + yc );
                this.pixel(  y + xc,  x + yc );
                this.pixel(  y + xc, -x + yc );
                this.pixel( -y + xc, -x + yc );
                this.pixel( -y + xc,  x + yc );
                if( d < 0 )
                    d += 4 * x + 6;
                else
                {
                    d += 4 * ( x - y ) + 10;
                    y--;
                }
                x++;
            }
        }
        this.text = function( x, y, str, className )
        {
            var el = document.createElement( 'DIV' );
            el.style.position = 'absolute';
            el.style.top = y + 'px';
            el.style.left = x + 'px';
            el.innerHTML = str;
            el.className = className;
            if( this.master == null )
                this.master = document.body;
            this.master.appendChild( el );
        }
    }

    var Timer = new function()
    {
        this.hour = -1;
        this.minute = -1;
        this.sec = -1;
        this.tid = null;

        this.getTime = function()
        {
            var d = new Date();
            var h = d.getHours();
            if( h > 11 )
                h -= 12;
            return { h: h, m: d.getMinutes(), s: d.getSeconds()};
        }
        this.set = function( func )
        {
            this.tid = setTimeout( func, 100 );
        }
    }
</script>
</head>
<body>
<h2>Hello Clock!</h2>
<div style="width: 500px; height: 450px; background: Gray; position: relative; overflow: hidden;">
<div id="field"></div>
<div id="fieldHour"></div>
<div id="fieldMin"></div>
<div id="fieldSec"></div>
</div>
<script type="text/javascript">
        var r = 150;
        var cx = 200;
        var cy = 200;

        Graph.container( document.getElementById( 'field' ));
        Graph.preset( 'gold', 2 );
        Graph.circle( cx, cy, r );
        Graph.text( 189, 20, '12', 'num' );
        Graph.text( 360, 188, '3', 'num' );
        Graph.text( 194, 355, '6', 'num' );
        Graph.text( 30, 188, '9', 'num' );


        var a6 = Math.PI/30;
        var a30 = Math.PI/6;

        for( var i = 0; i < 12; i++ )
            Graph.line( cx + Math.round(( r - 5 ) * Math.sin( i * a30 )), cy - Math.round(( r - 5 ) * Math.cos( i * a30 )), cx + Math.round( r * Math.sin( i * a30 )), cy - Math.round( r * Math.cos( i * a30 )));

        Graph.preset( 'Silver', 2 );

        for( var i = 0; i < 60; i++ )
            Graph.pixel( cx + Math.round(( r + 5 ) * Math.sin( i * a6 )), cy - Math.round(( r + 5 ) * Math.cos( i * a6 )));

        Graph.preset( '#CCFFFF', 2 );
        Graph.circle( cx, cy, 14 );

        var drawSec = function()
        {
            var t = Timer.getTime();

            if( t.h != Timer.hour )
            {
                Timer.hour = t.h;
                var el = document.getElementById( 'fieldHour' );
                el.innerHTML = '';
                Graph.container( el );
                Graph.preset( '#66CCFF', 5 );
                Graph.line( cx, cy, cx + Math.round(( r - 70 ) * Math.sin( t.h * a30 )), cy - Math.round(( r - 70 ) * Math.cos( t.h * a30 )));
            }
            if( t.m != Timer.minute )
            {
                Timer.minute = t.m;
                var el = document.getElementById( 'fieldMin' );
                el.innerHTML = '';
                Graph.container( el );
                Graph.preset( '#CCFFFF', 3 );
                Graph.line( cx + Math.round(( r - 135 ) * Math.sin( t.m * a6 )), cy - Math.round(( r - 135 ) * Math.cos( t.m * a6 )), cx + Math.round(( r - 40 ) * Math.sin( t.m * a6 )), cy - Math.round(( r - 40 ) * Math.cos( t.m * a6 )));
            }
            if( t.s != Timer.sec )
            {
                Timer.sec = t.s;
                var el = document.getElementById( 'fieldSec' );
                el.innerHTML = '';
                Graph.container( el );
                Graph.preset( 'White', 1 );
                Graph.line( cx + Math.round(( r - 100 ) * Math.sin( t.s * a6 )), cy - Math.round(( r - 100 ) * Math.cos( t.s * a6 )), cx + Math.round(( r - 85 ) * Math.sin( t.s * a6 )), cy - Math.round(( r - 85 ) * Math.cos( t.s * a6 )));
                Graph.circle( cx + Math.round(( r - 80 ) * Math.sin( t.s * a6 )), cy - Math.round(( r - 80 ) * Math.cos( t.s * a6 )), 5 );
                Graph.line( cx + Math.round(( r - 75 ) * Math.sin( t.s * a6 )), cy - Math.round(( r - 75 ) * Math.cos( t.s * a6 )), cx + Math.round(( r - 10 ) * Math.sin( t.s * a6 )), cy - Math.round(( r - 10 ) * Math.cos( t.s * a6 )));
            }
            Timer.set( "drawSec()" );
        }
        drawSec();
</script>
</body>
</html>

Автор: Sardar 26.9.2011, 13:30
Не актуально в свете canvas.

Автор: magelan 27.9.2011, 10:06
возможно. не буду спорить, каждый пишет для своих целей.

все мобильные устройства канвас держат?

Автор: SelenIT 27.9.2011, 13:15
Похоже, http://caniuse.com/#search=canvas. Сейчас, как ни парадоксально, в мобильном вебе можно смелее внедрять новшества, чем в десктопном, т.к. там преобладает Webkit и совсем нет старых IE... smile

Автор: magelan 28.9.2011, 10:12
Не смотря на присутствие iOS основная аудитория сидит на опере мини...
К тому же канвас это большой гиморой, когда надо сделать что-то простое. Например, стрелку поверх текста и картинки нарисовать, чтобы она от указанной точки на включенный чекбокс показывала.

Но да, погоня за модой... задоминировали, не надо не пользуйтесь.

Автор: ksnk 28.9.2011, 12:59
Цитата(magelan @  28.9.2011,  10:12 Найти цитируемый пост)
это большой гиморой, когда надо сделать что-то простое. Например, стрелку поверх текста и картинки нарисовать, чтобы она от указанной точки на включенный чекбокс показывала.

Не вижу гемороя... В смысле, бОльшего, чем с дивами. Их всех нужно точно так же, одинаково, привязывать к позиции.
Единственное отличие дивов от канваса - то, что канвас обязательно занимает прямоугольное полотно, пусть даже и прозрачное, а рисунок на дивах располагается попиксельно поверх контента. Из этого могут появится некоторые проблемы в распространении событий вниз, "под" рисунок. Большой прямоугольный канвас может их "перехватить" при невнимательном программировании. Зато с многодивным рисунком может возникнуть еще больше занимательных приключений с отметкой текста и пропажей событий. 

Автор: SelenIT 28.9.2011, 13:11
Насколько я понял пояснения на caniuse.com, Опера Мини (5+) умеет рисовать на канвасе статику, но не поддерживает скриптовую анимацию (т.к. скрипты в ней выполняются на сервере;). Т.е. игрушки на канвасе в ней не пойдут, но эту самую стрелку нарисовать ничто не помешает. Но пока не проверял...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)