CanvGauge — измерительный прибор с помощью canvas для HTML5

    HTML5 Canvas GaugeДобрый день, хабровчане!

    Сегодня я хочу поделиться своей небольшой разработкой, которую я делал для одного из своих проектов. На самом деле, в сети множество реализаций gauge, как платных, так и бесплатных. Но найти хоть одно решение с использованием именно canvas мне не удалось, поэтому было принято решение написать свое.

    Почему именно canvas?



    Во-первых, это работает во всех современных браузерах. Во-вторых — это таки работает на мобильных платформах Android и iOS без ограничений. Тот же SVG, к примеру не работает по-умолчанию на Android 2.x, а Flash не работает в iOS.

    Код CanvGauge можно забрать здесь. Там же можно найти небольшое описание API. А здесь посмотреть пример работы.

    При использовании вам не нужны никакие сторонние библиотеки. Код распространяется по лицензии MIT, можете спокойно забирать, модифицировать, улучшать/ухудшать, делиться своими дополнениями и наработками. С радостью приму хорошие коммиты в свой репозиторий. Буду признателен за найденные баги и интересные предложения. К сожалению, я не художник, поэтому внешний вид, возможно, не идеален. Если кто-то может помочь с наведением «красоты» — welcome!

    Особенности «из коробки»



    Gauge относительно легко кастомизируется. Можно задавать параметрически цвета элементов прибора, его размер, шкалы градаций, заголовок и единицы измерения. Доступны различные функции анимации стрелки, а также есть возможность внедрять свою функцию анимации «на лету».
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 67
    • +4
      Господа, если вы минусуете, то потрудидесь хотя бы в двух словах написать, что не так, по вашему мнению. Спасибо заранее.
      • +3
        Минусуют, наверное, потому что считают, что уже есть куча подобных примеров.
        Но т.к. сам не так давно искал подобный контрол и убедился, что толковых не так много, добавил пост в избранное.
        От себя в пост бы добавил изображения контрола и некоторую техническую информацию по его разработке и использованию.
        • +1
          Спасибо за рекомендации. Воспользовался вашим советом :)
          • +1
            Лучше расскажите как делали — какой фреймворк применяли и почему, как сделали анимацию, какие оптимизации и т.д.
            • +2
              Никаких фреймворков не применял — это оверхед для меня. Чиcтое Canvas 2D API для JS. Анимация методом перерисовки всего канваса. Оптимизаций пока не проводил. Текущая рабочая идея — рисовать подложку первый раз, потом отрисовывать как готовое изображение, рисовать при анимации в этом случае придется только стрелку и циферблат. Пока исследую эффестивность и работоспособность — не все гладко…
              • +1
                Что за оверхед от фреймворков?
                Что «не гладко»? Именно так и надо делать.
                • +1
                  Сам по себе фреймворк — оверхед в виде пачки кода. Если бы я делал библиотеку из овер 9000 компонентов — бон был бы нужен. Один контрол будет без фреймворка по кол-ву кода будет компактнее самого фреймворка. Поэтому я не нашел сакрального смысла в использовании какого-то фреймворка.

                  «Не гладко» — значит не работает покамест так как ожидается. Как только добьюсь положительного результата — будет сделан коммит.
                  • +2
                    Как-то вы очень агрессивно отвечаете.

                    Кешируйте вектр в растр — будет работать отлично. Проверено на практике.
                    • +1
                      TheShock, вам показалось. Я спокоен как слон. :) Если чем задел — простите.
                      Да я именно так и пытаюсь делать. Но есть 2 способа. Может вы поделитесь опытом какой эффективнее:

                      1. getImageData/putImageData — кешируем пиксели — пишем пиксели
                      2. создаем скрытый img c src= canvas.toDataURL(). Потом отрисовываем подложку с помощью drawImage() из этой картинки.

                      Проблемы у меня локального характера. В некоторых браузерах у меня проблемы с координатами при вызове get/put из первого способа. Т.е. не везде работает одинаково. Почему пока не разобрался.

                      • +2
                        Вот и славно, что спросили. Вы не учитываете третий, самый правильный способ — создать холст и отрисовывать потом холст как картинку:

                        // кешируем:
                        var cache = document.createElement('canvas');
                        cache.width  = 128;
                        cache.height= 128;
                        drawTo( cache.getContext('2d') );
                        
                        // отрисовываем из кеша:
                        targetCtx.drawImage( cache, 150, 150 );
                        
                        • +1
                          Отличная идея. Благодарю. Сейчас попробуем.
                          • +1
                            Способ рабочий. Единственно, что требует вставку кеширующего холста в DOM, иначе получаю глюки с отрисовкой текстовых элементов (Chrome 17, Ubuntu). В других браузерах пока не тестил. Кстати, чем это эффективней способа со скрытой картинкой и попиксельной отрисовкой? Вы тестировали?
                            • +1
                              Вопрос 23 и 26: habrahabr.ru/post/119772/
                              Странно, у меня никогда не было глюков с отрисовкой текстовых элементов, хотя я регулярно использую бек-буффер.
                              • 0
                                Сделал оптимизацию по вашему рецепту. Тем не менее глюк с текстовыми элементами присутствует. Могу сделать скриншот, если очень хотите увидеть. Вылечил именно реальной вставкой холста в DOM.
                                • 0
                                  лучше пример
                                  • 0
                                    Пожалуйста: ru.smart-ip.net/gauge2.html
                                    Разница только в том, что кеширующий холст не вставлен в DOM (закомментировано 2 строчки)
                                    • +1
                                      Проблема в использовании «em» здесь:
                                      ctx.font = (0.7 * max / 100) + "em Arial";

                                      em — относительная величина и размер считается относительно размера родителя. Родителя нету — размер нулевой.

                                      Вы рисуете на пиксельном холсте и потому измеряйте в пикселях)
                                      • 0
                                        Спасибо. Сейчас подфиксим.
                              • НЛО прилетело и опубликовало эту надпись здесь
                                • 0
                                  А где вам по ссылке необходима putImageData?
                                  И кстати, «все эффекты сразу» почему-то не работают (
          • 0
            А ничего, что проц на 70-80 процентов грузится?
            • 0
              У меня не грузится. Что у вас за конфигурация?
              • 0
                А если только один экземпляр на странице: smart-ip.net/gauge1.html — эффект тот же?
                • 0
                  На Макинтоше в Хроме эта вкладка испльзует 11% ЦПУ, а вкладка с тремя счетчиками 40% и вроде не тормозит, нормально работает.
                  Кстати красиво получилось
                • 0
                  У меня 20-25% загрузка. Процессор E6500 — весьма средний по сегодняшним меркам.
                  • 0
                    Q6600, Opera 11, 7-8% загрузки. Открыто еще несколько вкладок, правда.
                  • 0
                    Выглядит замечательно!

                    Но лицензия GPL исключает практическое использование этого кода. :( Давайте мож MIT/BSD или хотябы LGPL?
                    • +3
                      Давайте. Изменил на MIT. Спасибо за поправку. На самом деле — нет жалания ограничиать кого-бы то ни было в использовании. Тем более в практическом.
                      • 0
                        Отлично, спасибо! Буду использовать. Проект, к сожалению, внутренний, поэтому показать нечего. :)
                    • 0
                      Неплохо! В свое время на проекте надо было прикрутить такую штуку, единственное приемлемое решение было от гугла, но там юзается SVG+VML.

                      Хотя всё же не очень нравится когда в канвасе шрифты отличаются сглаживанием от шрифтов на странице.
                      • +1
                        Да, понимаю вас, сам начал именно с решения от Google. Потом осознал, что оно не будет работать нормально в Android 2.x и, после поисков, осознал, что придется писать свое.
                        • 0
                          Зато оно работает в Firefox 3.6, а Ваше — нет. Конечно, кому сейчас нужен Fx3.6? Но вот нам именно он-то и нужен, таковы условия разработки.
                          • +1
                            А теперь? Попробуйте открыть пример еще раз. Все работает?
                            • 0
                              Визуально теперь всё ОК. Добавлю статью в закладки, возможно, пригодится. Спасибо за заботу.
                            • 0
                              А зачем нужен Fx 3.6? Уже вышло 7 новых версий файрфокса.
                              • 0
                                Видать у людей корпоративная система заточенная под эту версию. Кстати, вся проблема была только в том, что context.arc() метод требует обязательного наличия параметра clockwise, который в спеке определен как опциональный. Но ФФ3.6 выкидывает ексепшн Too few arguments. Just FYI.
                                • 0
                                  Потому что он сертифицирован для использования в Минобороне.
                          • 0
                            Интернетометр сказал мне, что у меня на скачивание 35.73 Мбит/с при активном канале в 2Мбит. Врет однако, speedtest показывает более адекватный результат.
                            • 0
                              Спасибо за отчет. Это бета. Все еще работаем, проблемы имеют место быть. Если не сложно попробуйте перемерить несколько раз пе ред каждым измерением обновляя страницу. Скажите — как часто выдает заведомо завышенные результаты?
                              • 0
                                Раз 5 попробовал. 2 раза результат был завышен. Причем, долго показывает реальные цифры, потом резкий скачек и у меня скоростной интернет ))
                                • 0
                                  Спасибо огромное. Это очень не просто протестировать все на каналах разной толщины. Беру ваш отчет в оборот.
                                • 0
                                  Еще в том же «Интернетометре» смущают надписи на датчиках — «Скачивание» и «Загрузка». Не сразу понял что есть что :)

                                  Наверно было бы логичнее использовать антонимы («Скачивание»/«Закачивание» или «Загрузка»/«Отправка»).
                                • 0
                                  Speedtest показывает скорость до ближайшей точки.
                                  В интернете нет «адекватного» результата т.к. Вам провайдер дает доступ в интранет и через нее в интернет, а вот какие провайдеры дают доступ в интернет этому провайдеру и главное как — уже большой вопрос.
                                  • 0
                                    В Speedtest можно выбрать сервер. До ближайшего у меня честные 100Мбит/с. Я намеренно выбрал сервер где-то в Киеве.
                                • 0
                                  пример не открывается
                                  • 0
                                    Эх… попробуй выдержать всех вас :) Сервер у меня дохленький совсем…
                                    • +2
                                      Разгрузил немного — должен работать теперь (пришлось временно остановить один сервис)
                                  • 0
                                    Прикольный эффект — кажется, что цифры на жк дисплее имеют наклон влево.
                                    • 0
                                      У замечательной библиотеки jqPlot есть куча рендерреров, не говоря уже о механизме их написания. Там так же есть рендеррер, позволяющий сделать из графика спидометр.
                                      • 0
                                        Не нашел в примерах. Можете дать ссылку? Анимацию поддерживает?
                                        • +1
                                          Вот здесь можно посмотреть нативный пример, который можно допилить по собственным нуждам как угодно :)
                                          www.jqplot.com/deploy/dist/examples/meterGauge.html

                                          Если под анимацией подразумевается динамическая перерисовка графика по таймауту — то да, у меня на проекте такое реализовал как раз недавно.
                                          • 0
                                            Спасибо, интересно. Хотя и не совсем то, что мне нужно. Как я понял для приведения к нужному виду придется написать свой рендерер. Но библиотека действительно интересная. Спасибо за ссылку.
                                            • 0
                                              Да, придется писать свой. Но в этом и прелесть данной библиотеке, в такой возможности. Хотя для большинства задач она слишком навороченная, там одних только настроек на целый txt файл.
                                              • 0
                                                Если придется писать свой, то по объему это сопоставимо с проделанной работой. Я вот и написал свой. Вне контекста какой-либо библиотеки, так как мне нужен только один контрол. Но если нужно будет написать 100+ контролов, такая библиотека просто супер.
                                                • 0
                                                  В чём-то даже проделанная Вами работа выигрывает — писать с нуля и только для себя в общем-то и проще, и быстрее, как мне кажется.
                                                  Ссылкой я поделился не из принципа «зачем писать велосипед», а из принципа «может быть кому-то пригодится» :)
                                                  • 0
                                                    Да, я просто пытаюсь выставить факт отсутсвия каких-либо библиотек, как достоинство своего решения. :D Для тех, кто читает. Я не спорю с вами, и, действительно, нахожу вашу ссылку интересной :)
                                      • 0
                                        Красиво. Я помню, насколько было трудно сделать похожее в 2009г. в OpenLaszlo )
                                        • 0
                                          Совместимость с какими браузерами?

                                          В setInterval по умолчанию 15 миллисекунд если поставить, то по идее сильной разницы не будет, а процессор разгрузите, щас стабильно 20 съедает.
                                          • 0
                                            Эта опция отдана на откуп пользователю — можете конфигурировать кол-во миллисекунд по собственному усмотрению
                                            • 0
                                              > Совместимость с какими браузерами?

                                              По-идее со всеми, которые поддерживают HTML5 и canvas
                                            • +1
                                              А зачем вы в конце каждого метода делаете?
                                              ctx.restore();
                                              ctx.save();
                                              • 0
                                                Так там еще есть много мест где подчистить код не будет лишним. Ну и в множестве случаем ctx.restore() необходим, так как при прорисовке приходится канву вертеть в разные стороны.
                                                • +1
                                                  корректно будет «оборачивать» метод. как-то так:
                                                  method: function () {
                                                    ctx.save();
                                                    // change ctx
                                                    ctx.restore();
                                                  }
                                                  
                                            • +1
                                              Скажите, Ваш CanvGauge не навеян вот этим Aqua Gauge ? Я просто сам недавно переписывал его под две стрелки для использования как измеритель In и Out траффика. Там изначально автор использует лицензию MIT.
                                              • 0
                                                Нет, я до этого Aqua Gauge не встречал. Т.к. если бы встретил — вряд ли бы писал свой :) Спасибо за ссылку. Поковырял. Нравится :) Только анимации не хватает. Наверное воьзму пару идей оттуда к себе. Еще раз спасибо за ссылку.
                                                • 0
                                                  Кстати, лицензия там не MIT, а CPOL

                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.