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


Автор: kuksha 14.2.2015, 23:21
Есть страница, в которой JavaSvript рисует в Canvas некий рисунок.
Кроме этого рисунка на странице много что понаписано на PHP.
Нужно распечатать только рисунок, без остального мусора на странице.
Как это сделать?

Автор: ksnk 15.2.2015, 11:40
Alt-PrtSc, вставить в фотошоп, вырезать ненужное, распечатать?

Страница, которая преднаначена для печати, обычно, специально формируется. Если хозяин страницы не пожелал делать такую опцию - остается фотошоп

Автор: diadiavova 15.2.2015, 12:56
В принципе, если речь идет о яваскрипт-решении и страница загружена в браузер, то можно написать букмарклет, вроде такого
Код

javascript: (function ()
{
    var newwin = open("about:blank");
    var cl = document.querySelectorAll("canvas");
    newwin.addEventListener("load", function ()
    {
        var doc = newwin.document;
        for (var i = 0; i < cl.length; i++)
        {
            var img = doc.createElement("img");
            img.src = cl[i].toDataURL();
            doc.body.appendChild(img);
        }
    }, false)
})();
Он откроет новую страницу и вставит изображения с канвасов как картинки, ну а картинки уже можно сохранить штатными инструментами браузера.

ЗЫ
Код проверял только в файрфоксе. На вот этой странице работает
http://www.w3schools.com/html/html5_canvas.asp
А вот на этой - не хочет
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
Но здесь канвас оказывается внутри фрейма, так что если открыть саму страницу фрейма
https://mdn.mozillademos.org/en-US/docs/Web/API/Canvas_API$samples/Playable_code?revision=726957
То на ней все заработает как следует.

Автор: Aliance 16.2.2015, 08:53
Так пробовали?
Код

@media print {
    * { display: none; }
    body, canvas { display: block; }
}

Автор: kuksha 16.2.2015, 22:08
Cтраница на моём сайте - могу всё что угодно делать.
В идеале хотелось бы кнопку с вызовом функции JavaScript, чтобы выскакивало что-то вроде диалога как при вызове window.print()

ksnk, принтскрин уже предлагал, но народ ленивый...

diadiavova, да, вариант, спасибо. Но, многовато действий + в новом окне не каждый догадается зайти в меню для распечатывания. Как бы без промежуточного окна обойтись...

Aliance, не осилил... можно поподробнее что это такое и что с этим делать?


Может быть есть способ сохранить содержимое канвы в каком-то контейнере (в области памяти, в файле...) и потом вызвать печать этого контейнера?

Автор: diadiavova 16.2.2015, 22:52
Цитата(kuksha @  16.2.2015,  22:08 Найти цитируемый пост)
diadiavova, да, вариант, спасибо. Но, многовато действий + в новом окне не каждый догадается зайти в меню для распечатывания. Как бы без промежуточного окна обойтись...

Да свободно можно обойтись. Код практически тот же( с некоторыми изменениями), просто я думал это тебе надо, а не на сайте. Ну собственно кнопочку делаешь, и по нажатию выполняешь код. Результат можно вставить в контейнер на странице или заранее разместить там картинку и просто передавать ей урл картинки.
Ну вот набросал пример, код для заполнения канваса стырил http://habrahabr.ru/post/111308/. 
Код

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <canvas id="canvas1"></canvas>
    <button id="btn1">Нарисовать</button>
    <img src="#" alt="Картинка копируется сюда" id="img1" />
    <script>
        var canvas1 = document.getElementById("canvas1");
        var img1 = document.getElementById("img1");
        document.getElementById("btn1").addEventListener("click", function ()
        {
            img1.src = canvas1.toDataURL();
        });
        var ctx = canvas1.getContext("2d");
        
        canvas1.width = 320;
        canvas1.height = 320;
        ctx.strokeRect(15, 15, 266, 266);
        ctx.strokeRect(18, 18, 260, 260);
        ctx.fillRect(20, 20, 256, 256);
        for (i = 0; i < 8; i += 2)
            for (j = 0; j < 8; j += 2)
            {
                ctx.clearRect(20 + i * 32, 20 + j * 32, 32, 32);
                ctx.clearRect(20 + (i + 1) * 32, 20 + (j + 1) * 32, 32, 32);
            }
    </script>
</body>
</html>

Правда пока проверял, заметил, что в лисе канвас можно сохранить как изображение, просто в контекстном меню есть пункт "Сохранить изображение как...", а еще можно открыть изображение и тогда оно в новой вкладке откроется. В хроме и опере тоже есть возможность сохранить, так что такой код может понадобиться только для ИЕ

Автор: kuksha 16.2.2015, 23:08
Ого... никогда не замечал, что можно канву сразу в картинку сохранять...

Приведённый код конечно приколен, но мне печать на принтере нужна, а не копирование. 
Либо я чего-то не вижу.

Автор: diadiavova 16.2.2015, 23:12
Цитата(kuksha @  16.2.2015,  23:08 Найти цитируемый пост)
Либо я чего-то не вижу. 

Я подумал, что проблема в канвасе, а с изображением проблем нет. Просто о печати мне ничего не известно smile Но сохранить ведь изображение можно, а потом отпечатать - тоже не проблема. Да и открытие в отдельной вкладке вроде вполне решает проблему. Засунул туда изображение и печатай сколько влезет, не? : smile 

Автор: kuksha 16.2.2015, 23:21
нет, это не то, я уже писал почему.

Ещё раз:
Нужна кнопка с привязанным скриптом печати на принтер содержимого канваса с данной страницы.
Aliance, поясните пожалуйста ваш способ - не понимаю...

Автор: diadiavova 17.2.2015, 12:10
Цитата(kuksha @  16.2.2015,  23:21 Найти цитируемый пост)
Нужна кнопка с привязанным скриптом печати на принтер содержимого канваса с данной страницы.

Ну тогда вариант, предложенный Aliance, только с некоторыми изменениями. Если блоки схлопнуты с помощью display:none, то открыть канвас не получится из-за того, что скрыты родительские элементы. Надо сделать так
Код

@media print{
            body {visibility:hidden;}
            canvas{visibility:visible; position:absolute; top:0;left:0; }
        }

Ну и добавить кнопку
Код

       <button onclick="print();">Печатать</button>

Автор: Aliance 17.2.2015, 12:14
Цитата(kuksha @  16.2.2015,  23:08 Найти цитируемый пост)
в новом окне не каждый догадается зайти в меню для распечатывания. Как бы без промежуточного окна обойтись...

Так а что мешает при открытии окна вызвать window.print()?

Цитата(kuksha @  17.2.2015,  00:21 Найти цитируемый пост)
Aliance, поясните пожалуйста ваш способ - не понимаю... 

Вы пробовали его? Ну или гуглили, что такое @media print?

Вы, мне кажется, не до конца уточнили детали задачи - кто должен печатать и при какиХ обстоятельствах? Если нужна кнопка, нажимая на которую пользователям предлагается вывести страницу на печать, где будет только канвас - то вот: http://jsfiddle.net/9f4msqej/ , стили можете взять выше, они более правильные.

Автор: kuksha 17.2.2015, 13:00
Да я вроде подробно написал:
У меня есть сайт, на сайте страничка с ТЕКСТОМ и РИСУНКОМ который сделан сриптом JavaScript в Canvas.
Нужна кнопка на этой страничке, чтобы печатался только РИСУНОК, без ТЕКСТА, через вызов диалога печати.

Цитата(Aliance @  17.2.2015,  12:14 Найти цитируемый пост)
 Если нужна кнопка, нажимая на которую пользователям предлагается вывести страницу на печать, где будет только канвас - то вот: http://jsfiddle.net/9f4msqej/

Да, так и нужно, но что-то там не так прописано: 
Нажал на кнопку в этом примере - вызвался диалог печати, но в предварительном просмотре печати написано "Произошла ошибка предварительного просмотра печати".

Кстати, у меня не текстовый див:
Код

<div id="canvas">допустим, что этот блок - это ваш печатуемые канвас.</div>

а рисунок:
Код

<div id="canvas-frame" style="position:relative;width:650px;height:650px;overflow:visible">
<canvas id="karta" width="650" height="650"></canvas>
</div>

ну и далее в этот канвас "karta" всё рисуется скриптом... надеюсь это не помешает печати?

ПС: сейчас попробовать не могу, только вечером, но хотелось бы сейчас понять что в примере не так - вроде всё прозрачно, но что за ошибка...

Автор: kuksha 17.2.2015, 14:13
Всё получилось!
Спасибо всем помогавшим! smile

Вот только неприятность маленькая:
Вместе с рисунком на печать выводится реклама Гугл, которая вызывается гугловским же скриптом.
Как бы рекламу убрать?

CSS сделано так:
Код

@media print {
    body {visibility:hidden;}
    #canvas-frame {visibility:visible; }
}

А рабочий черновик посмотреть можно здесь:
http://kosmoved.ru/nebo_segodnya_geo_14.php

Автор: ksnk 17.2.2015, 14:28
kuksha, Для печати звездного неба лучше белый фон. Так что в этом случае - правильнее специальный канвас вставлять с картой и белым фоном. Из основного можно только центр и зум забрать

Автор: kuksha 17.2.2015, 14:34
ksnk,  для печати в карте есть Ч/Б режим.
А вот как всё-же Гугл-рекламу убрать?

Автор: diadiavova 17.2.2015, 14:45
kuksha, а вот у меня отпечатался белый лист. Скорей всего из-за того, что в стиле прописан див, а не канвас и на канвас распространяется общее правило, заданное для тела. Пробовал в файрфоксе. Но заменил селектор #canvas-frame на #canvas-frame canvas и все заработало как надо.

Автор: kuksha 17.2.2015, 14:55
diadiavova, очень странно, я смотрел в Хроме - несколько карт напечатал...
Но, послушался Вас и заменил сейчас CSS на:
Код

@media print {
    body {visibility:hidden;}
    #canvas-frame canvas {visibility:visible; }
}

Изменений не увидел - на предпросмотре всё точно как и было, но может быть в Фаерфоксе что-то изменилось?

и ещё эта реклама Гугловская... у кого есть соображения как её убрать?

Автор: diadiavova 17.2.2015, 15:04
Цитата(kuksha @  17.2.2015,  14:55 Найти цитируемый пост)
но может быть в Фаерфоксе что-то изменилось?

Сейчас нормально. Перед тем, как писать, я сначала сам заменил селектор в файрбаге. 
Цитата(kuksha @  17.2.2015,  14:55 Найти цитируемый пост)
и ещё эта реклама Гугловская... у кого есть соображения как её убрать?

В файрфоксе нет никакой рекламы, но хром может и выдает, это ж гугловский браузер smile

Добавлено через 8 минут и 27 секунд
div#adunit{display:none} не срабатывает что ли? Это насчет рекламы.

Автор: kuksha 17.2.2015, 16:00
Понятно, спасибо.
А рекламу я сам туда поставил, вот только непонятно откуда на печати она  взялась...

Поставил так:
Код

@media print {
    body {visibility:hidden;}
    div#adunit{display:none; visibility:hidden;}
    #canvas-frame canvas {visibility:visible; }
}

 - всё равно реклама лезет...

Автор: diadiavova 17.2.2015, 16:24
Цитата(kuksha @  17.2.2015,  16:00 Найти цитируемый пост)
Поставил так:

Я в первый раз не заметил, но эта реклама во фрейме находится и из-за этого на нее не распространяются правила. Фрейм скрывать надо
#google-adds-frame1{display:none}

Цитата(kuksha @  17.2.2015,  16:00 Найти цитируемый пост)
display:none; visibility:hidden;

display:none работает так же, как visibility:collapsed, так что в данном случае правила противоречат друг другу. Выполнится какое-то одно, хотя в данном случае это вряд ли имеет значение.

Автор: kuksha 17.2.2015, 16:38
Оба правила я поставил уже напоследок - пробовал их поочереди...

Заменил сейчас это правило на 
#google-adds-frame1{display:none}
не помогает...
#aswift_0_expand{display:none}
тоже не срабатывает

Автор: diadiavova 17.2.2015, 17:03
Цитата(kuksha @  17.2.2015,  16:38 Найти цитируемый пост)
#google-adds-frame1{display:none}

Там на самом деле ид google_ads_frame1, я просто написал с ошибкой.

Автор: kuksha 17.2.2015, 17:23
Не, я до написания копировал имя фрейма напрямую со страницы (а здесь из топика скопировал..) - не работает...

Автор: diadiavova 17.2.2015, 18:36
kuksha, короче, первый вариант, который я предложил, содержал селектор body *, потом я отредактировал пост и заменил просто на body, но судя по всему с рекламой поможет справиться именно тот вариант.

Автор: kuksha 17.2.2015, 19:05
УРА!!! smile
Действительно, дело в звёздочке...
Код

@media print {
    body * {visibility:hidden;}
    #canvas-frame canvas {visibility:visible; }
}


У меня правда почему-то 4 страницы для печати, хотя рисунок только на первой, но так видимо получается на основе общей высоты страницы. Ладно - пусть юзвери сами смотрят и редактируют...

Спасибо огромное!!!  smile 

Автор: diadiavova 17.2.2015, 20:01
Цитата(kuksha @  17.2.2015,  19:05 Найти цитируемый пост)
У меня правда почему-то 4 страницы для печати

Там же в диалоге печати можно установить какие страницы надо на печать выводить.

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