Görüntüye HTML oluşturma


167

PNG gibi resme html oluşturmanın bir yolu var mı? Tuval ile mümkün olduğunu biliyorum ama örneğin div gibi standart html elemanını işlemek istiyorum.


Örneğin, bir tür kullanıcı yardımı oluşturmak için. Ne yazık ki, bu mümkün değil (güvenlik nedeniyle?). Bir şey yapmak için kullanıcıdan PrintScreen'e basmasını istemeniz gerekir.
MaxArt


Bir logo tasarlamak için HTML / CSS kullanmak istiyorum.
Martin Delille

4
@ ErnestFriedman-Hill kopya değil: bahsettiğiniz soru java'ya özgüdür.
Martin Delille

İşte HTML PNG veya jpeg formatında kod
Satinder singh

Yanıtlar:


42

Bunun zaten çok fazla cevabı olan oldukça eski bir soru olduğunu biliyorum, ancak hala istediğimi yapmaya çalışarak saatler geçirdim:

  • bir html dosyası verildiğinde , komut satırından saydam arka planı olan bir (png) resmi oluşturun

Chrome başsız (bu yanıttan itibaren sürüm 74.0.3729.157) kullanmak aslında kolaydır:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless --screenshot --window-size=256,256 --default-background-color=0 button.html

Komutun açıklaması:

  • Chrome'u komut satırından çalıştırırsınız (burada Mac için gösterilir, ancak Windows veya Linux'ta benzer olduğu varsayılarak)
  • --headless Chrome'u açmadan çalıştırır ve komut tamamlandıktan sonra çıkış yapar
  • --screenshotbir ekran görüntüsü yakalar ( screenshot.pngkomutun çalıştırıldığı klasörde çağrılan bir dosya oluşturduğunu unutmayın )
  • --window-sizeekranın yalnızca bir kısmını yakalamaya izin ver (biçim --window-size=width,height)
  • --default-background-color=0Chrome'a varsayılan beyaz rengi değil şeffaf bir arka plan kullanmasını söyleyen sihir
  • Son olarak html dosyasını sağlarsınız (yerel veya uzak bir url olarak ...)

1
Çok hoş! SVG ile de çalışır! Sonunda çözümünüze geçtim! ;-)
Martin Delille 03

1
--screenshot='absolute\path\of\screenshot.png'benim için çalıştı
palash

comman hattı çalıştı. Eğer bu ekspres js programlı çalıştırmak için nasıl çalıştırmak için?
Squapl Tarifler

Bilginize, man sayfasındaki seçenekten bahsetmese de krom ile birlikte çalışır.
Robin Lashof-Regas

Svg benim için bir svg değil ... sadece SVG uzantılı bir PNG ... dikkat edin.
kristopolous

97

Evet. HTML2Canvas , HTML'yi oluşturmak için var <canvas>(daha sonra resim olarak kullanabilirsiniz).

NOT: Bunun SVG ile çalışmayacağı bilinen bir sorun var


İlginç görünüyor ama işe yaramadı, bu yüzden John Fisher çözümünü seçtim. Bilgi için teşekkürler, gelecekte bu projeyi izleyeceğim!
Martin Delille

@MartinDelille: burada IMAGE oluşturmak için HTML2Canvas kullanma makalesi ve aynı zamanda istemci tarafında codepedia.info/2016/02/…
Satinder singh

3
Dom-to-image (tsayen'in cevabına bakın), doğru bir resim oluşturmak için çok daha iyi bir iş çıkarır.
JBE

3
Bu çözüm çok yavaş
hamboy75

3
başka bir sorun, öğe gizli veya başka bir öğenin arkasında ise bu işe yaramaz
Yousef

91

Ben sadece bu sorunu çözmek için yazılmış dom-görüntü kitaplığı tavsiye edebilir miyim (ben koruyucusuyum).
Bunu nasıl kullanacağınız (bazıları burada ):

var node = document.getElementById('my-node');

domtoimage.toPng(node)
    .then (function (dataUrl) {
        var img = new Image();
        img.src = dataUrl;
        document.appendChild(img);
    })
    .catch(function (error) {
        console.error('oops, something went wrong!', error);
    });

2
Bu harika! Çıktı boyutunu ikiye katlamanın herhangi bir yolu var mı?
cronoklee

Teşekkürler! Peki "boyutu iki katına çıkarmak" ile tam olarak ne demek istiyorsun?
tsayen

2
Aklıma gelen ilk şey - resminizi SVG'ye (kullanarak domtoimage.toSvg) dönüştürmeye çalışın, sonra kendiniz tuval üzerine renderlayın ve bir şekilde o tuvalin çözünürlüğü ile oynamayı deneyin. Büyük olasılıkla lib'in kendisinde bir tür oluşturma seçeneği gibi bir özellik uygulamak mümkündür, böylece görüntü boyutlarını piksel cinsinden geçirebilirsiniz. İhtiyacınız olursa, github'da bir sorun oluşturmanızı takdir ediyorum.
tsayen

8
Bu html2canvas'dan çok daha iyi. Teşekkürler.
c.hughes

1
@Subho, base64 kodlu verilerle URL'yi içeren bir Dize
tsayen

66

Çok fazla seçenek var ve hepsinin pro ve eksileri var.

Seçenek 1: Mevcut birçok kütüphaneden birini kullanın

Artıları

  • Dönüşüm çoğu zaman oldukça hızlı

Eksileri

  • Kötü oluşturma
  • Javascript çalıştırmaz
  • Son web özellikleri için destek yok (FlexBox, Gelişmiş Seçiciler, Web Yazı Tipleri, Kutu Boyutlandırma, Medya Sorguları, ...)
  • Bazen kurulumu o kadar kolay değil
  • Ölçek için karmaşık

Seçenek 2: PhantomJ'ler ve belki de bir sarıcı kitaplığı kullanın

Artıları

  • Javascript Yürüt
  • Oldukça hızlı

Eksileri

  • Kötü oluşturma
  • Son web özellikleri için destek yok (FlexBox, Gelişmiş Seçiciler, Web Yazı Tipleri, Kutu Boyutlandırma, Medya Sorguları, ...)
  • Ölçek için karmaşık
  • Yüklenecek resimler varsa çalışmasını sağlamak o kadar kolay değil ...

3. Seçenek: Chrome Başsız ve belki bir sarmalayıcı kitaplığı kullanın

Artıları

  • Javascript Yürüt
  • Mükemmel görüntülemeye yakın

Eksileri

  • Aşağıdakilerle ilgili istenen sonuca sahip olmak o kadar kolay değil:
    • sayfa yükleme zamanlaması
    • görünüm alanı boyutları
  • Ölçek için karmaşık
  • Html harici bağlantılar içeriyorsa oldukça yavaş ve daha yavaş

4. Seçenek: Bir API kullanın

Artıları

  • Javascript Yürüt
  • Mükemmel görüntülemeye yakın
  • Önbellek seçenekleri doğru kullanıldığında hızlı
  • Ölçek API'lar tarafından yönetilir
  • Hassas zamanlama, görüntü alanı, ...
  • Çoğu zaman ücretsiz bir plan sunarlar

Eksileri

  • Onları çok kullanmayı planlıyorsanız ücretsiz değil

Açıklama: ApiFlash'ın kurucusuyum. Dürüst ve faydalı bir cevap vermek için elimden geleni yaptım.


2
Çok sayıda olası çözüm içeren ayrıntılı bir yanıt için teşekkür ederiz
bszom

wkhtmltoimage / pdf javascript oluşturmayı destekler. Bir javascript gecikmesi ayarlayabilir veya wkhtml'in belirli bir window.status'u kontrol etmesine izin verebilirsiniz (bu, js öğelerinizin yapıldığını bildiğinizde javascript ile ayarlayabilirsiniz)
Daniel Z.

PhantomJS, Google Haritalar gibi dinamik öğeleri destekler. Gerçekten bir ekran bağlı olmadan tam bir web tarayıcısı. Bununla birlikte, Google Map'in fayansları coğrafyaya yüklemesi için biraz beklemeniz gerekiyor (500 ms bekliyorum ve insanların gecikmeyi değiştirmesine izin veriyorum - yeterli değilse, zamanı arttırmadan tekrar çalıştırmak iyidir, çünkü bu fayanslar önbelleğe alınır).
Ladislav Zima

50

Buradaki tüm yanıtlar üçüncü taraf kitaplıklarını kullanırken bir görüntüye HTML oluştururken saf Javascript'te nispeten basit olabilir. Orada olduğunu bile oldu bu konuda bir makale MDN'yi üzerinde tuval bölümünde.

İşin püf noktası şudur:

  • XHTML'nizi içeren bir foreignObject düğümü olan bir SVG oluşturun
  • görüntünün src'sini bu SVG'nin veri URL'sine ayarlama
  • drawImage tuval üzerine
  • tuval verilerini image.src'yi hedef alacak şekilde ayarlama

const {body} = document

const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = canvas.height = 100

const tempImg = document.createElement('img')
tempImg.addEventListener('load', onTempImageLoad)
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><style>em{color:red;}</style><em>I</em> lick <span>cheese</span></div></foreignObject></svg>')

const targetImg = document.createElement('img')
body.appendChild(targetImg)

function onTempImageLoad(e){
  ctx.drawImage(e.target, 0, 0)
  targetImg.src = canvas.toDataURL()
}

Dikkat edilmesi gereken bazı şeyler

  • SVG'nin içindeki HTML XHTML olmalıdır
  • Güvenlik nedeniyle, görüntünün veri url'si olarak SVG, harici kaynaklar yüklenemediğinden HTML için yalıtılmış bir CSS kapsamı görevi görür. Yani örneğin bir Google yazı gibi bir araç kullanarak satır içine yerleştirilmiş zorundadır bu bir .
  • SVG'nin içindeki HTML görüntünün boyutunu aşsa bile tuval üzerine doğru şekilde çizilir. Ancak gerçek yükseklik bu görüntüden ölçülemez. Sabit yükseklik çözümü gayet iyi çalışır ancak dinamik yükseklik biraz daha fazla çalışma gerektirir. En iyisi, SVG verilerini bir iframe'e (izole CSS kapsamı için) dönüştürmek ve elde edilen boyutu tuval için kullanmaktır.

Güzel! Harici kütüphane bağımlılığını kaldırmak gerçekten iyi bir yoldur. Kabul edilen cevabımı değiştirdim :-)
Martin Delille

Bu makale artık orada değil.
MSC

2
Harika bir cevap, ancak her zamanki gibi birisinin arkasından bir şey çıkmış gibi görünen HTML ve Web API'lerinin sanat durumu hakkında yorum yapmak - tüm işlevsellik teknik olarak oradadır, ancak benzeyen garip kod yollarının bir dizisinin (punta amacı yoktur) arkasına maruz kalmıştır iyi tasarlanmış API'lerden beklediğiniz netlik türünden hiçbir şey. Plainspeak'te: bir tarayıcının a'nın Documentbir raster haline getirilmesine izin vermesi büyük olasılıktır (örneğin a Canvas), ancak kimse standartlaştırmak için uğraşmadığından, yukarıda gösterildiği gibi deliliğe başvurmalıyız (bunun yazarına suç yok) kodu).
amn

1
Bu cevap stackoverflow.com/questions/12637395/… oldukça ileri gidebileceğinizi gösteriyor gibi görünüyor. Mozilla ve Chrome sınırsız veri uri uzunluğuna sahiptir ve hatta mevcut IE, yaklaşık 3GB görüntülere (base64 nedeniyle) kadar kaybolan 4GB'a izin verir. Ama bu test etmek için iyi bir şey olurdu.
Sjeiti

3
- daha sonra bazı hızlı ve kirli testler - jsfiddle.net/Sjeiti/pcwudrmc/75965 Chrome, Edge ve Firefox, (bu durumda) yaklaşık 10.000.000 karakter sayısı ve png dosya boyutu olan en az 10.000 piksel genişliğe kadar çıkar 8MB. Titizlikle test etmedim, ancak çoğu kullanım durumu için yeterlidir.
Sjeiti

13

Başsız bir webkit (safari ve (yakın zamana kadar krom işleme platformu ) sürücüsü olan PhantomJS'yi kullanabilirsiniz . Sayfaların ekran yakalama yapmak öğrenebilirsiniz burada . Umarım yardımcı olur!


Bu teknik iyi çalışıyor. Ancak, yorumunuzdan bu yana 2 yıl geçti. PhantomJS'den daha hızlı çalışan bir şeyle karşılaştınız mı? Image Generation benim tecrübelerime göre Phantom'da genellikle 2-5 saniye sürüyor.
Brian Webster

Başsız Chrome artık mümkün. Daha hızlı olup olmadığını bilmiyorum, ancak doğru ekran görüntüleri istiyorsanız, bu iyi bir yoldur.
Josh Maag

11

Wkhtmltopdf gibi bir HTML'den PDF'ye aracını kullanabilirsiniz. Ve sonra imagemagick gibi bir görüntü aracı için PDF kullanabilirsiniz. Kuşkusuz bu sunucu tarafı ve çok kıvrımlı bir süreç ...


12
Veya sadece wkhtmltopdf'in görüntü kardeşi wkhtmltoimage'yi çalıştırabilirsiniz.
Roman Starkov

1
Bu kütüphane içindir Node.js. Basit ön uca ne dersiniz?
Vlad

9

Chrome, Firefox ve MS Edge için çalışmam gereken tek kütüphane rasterleştirildiHTML . HTML2Canvas'tan daha kaliteli çıktı ve HTML2Canvas'ın aksine hala destekleniyor.

Öğe Alma ve PNG Olarak İndirme

var node= document.getElementById("elementId");
var canvas = document.createElement("canvas");
canvas.height = node.offsetHeight;
canvas.width = node.offsetWidth;
var name = "test.png"

rasterizeHTML.drawHTML(node.outerHTML, canvas)
     .then(function (renderResult) {
            if (navigator.msSaveBlob) {
                window.navigator.msSaveBlob(canvas.msToBlob(), name);
            } else {
                const a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                a.href = canvas.toDataURL();
                a.download = name;
                a.click();
                document.body.removeChild(a);
            }
     });

2
ancak IE ile çalışmaz. HTML Sınırlamaları
Boban Stojanovski

@vabanagas Bunun için tek bir dosya javascript var mı?
Mehdi Khalili

Bu değişiklik bana çok yardımcı oldu: rasterizeHTML.drawHTML(node.innerHTML, canvas) Düğümde innerHTML çağırıyorum
Eylül GH

5

HTML'yi Tuval'e dönüştürmek için eklenti ve çağrı yöntemini içeren html2canvas kullanın ve ardından resim PNG olarak indirin

        html2canvas(document.getElementById("image-wrap")).then(function(canvas) {
            var link = document.createElement("a");
            document.body.appendChild(link);
            link.download = "manpower_efficiency.jpg";
            link.href = canvas.toDataURL();
            link.target = '_blank';
            link.click();
        });

Kaynak : http://www.freakyjolly.com/convert-html-document-into-image-jpg-png-from-canvas/


4

Bunun en iyi cevap olmasını beklemiyorum, ancak göndermek için yeterince ilginç görünüyordu.

Favori tarayıcınızı istediğiniz HTML belgesine açan, pencereyi doğru şekilde boyutlandıran ve ekran görüntüsü alan bir uygulama yazın. Ardından, görüntünün kenarlıklarını kaldırın.


4

Bu kodu kullanın, kesinlikle işe yarayacaktır:

<script type="text/javascript">
 $(document).ready(function () {
	 setTimeout(function(){
		 downloadImage();
	 },1000)
 });
 
 function downloadImage(){
	 html2canvas(document.querySelector("#dvContainer")).then(canvas => {
		a = document.createElement('a'); 
		document.body.appendChild(a); 
		a.download = "test.png"; 
		a.href =  canvas.toDataURL();
		a.click();
	});	 
 }
</script>

Html2CanvasJS dosyasını programınıza eklemeyi unutmayın. https://html2canvas.hertzen.com/dist/html2canvas.js


2

Bunu yalnızca% 100 JavaScript ile doğru şekilde yapamazsınız.

Orada bir Qt Webkit aracı ve bir python sürümü var . Kendiniz yapmak isterseniz, Kakao ile başarılı oldum:

[self startTraverse:pagesArray performBlock:^(int collectionIndex, int pageIndex) {

    NSString *locale = [self selectedLocale];

    NSRect offscreenRect = NSMakeRect(0.0, 0.0, webView.frame.size.width, webView.frame.size.height);
    NSBitmapImageRep* offscreenRep = nil;      

    offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
                                             pixelsWide:offscreenRect.size.width
                                             pixelsHigh:offscreenRect.size.height
                                             bitsPerSample:8
                                             samplesPerPixel:4
                                             hasAlpha:YES
                                             isPlanar:NO
                                             colorSpaceName:NSCalibratedRGBColorSpace
                                             bitmapFormat:0
                                             bytesPerRow:(4 * offscreenRect.size.width)
                                             bitsPerPixel:32];

    [NSGraphicsContext saveGraphicsState];

    NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
    [NSGraphicsContext setCurrentContext:bitmapContext];
    [webView displayRectIgnoringOpacity:offscreenRect inContext:bitmapContext];
    [NSGraphicsContext restoreGraphicsState];

    // Create a small + large thumbs
    NSImage *smallThumbImage = [[NSImage alloc] initWithSize:thumbSizeSmall];  
    NSImage *largeThumbImage = [[NSImage alloc] initWithSize:thumbSizeLarge];

    [smallThumbImage lockFocus];
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
    [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
    NSBitmapImageRep *smallThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
    [smallThumbImage unlockFocus];  

    [largeThumbImage lockFocus];  
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
    [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
    NSBitmapImageRep *largeThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
    [largeThumbImage unlockFocus];  

    // Write out small
    NSString *writePathSmall = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_small.png", locale, collectionIndex, pageIndex]];
    NSData *dataSmall = [smallThumbOutput representationUsingType:NSPNGFileType properties: nil];
    [dataSmall writeToFile:writePathSmall atomically: NO];

    // Write out lage
    NSString *writePathLarge = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_large.png", locale, collectionIndex, pageIndex]];
    NSData *dataLarge = [largeThumbOutput representationUsingType:NSPNGFileType properties: nil];
    [dataLarge writeToFile:writePathLarge atomically: NO];
}];

Bu yardımcı olur umarım!


Yukarıdakilerin hızlı bir sürümü var mı? ya da mümkünse lütfen yeniden yazabilir misiniz?
ssh

Oluşturduğunuz webView'ı yüklemek için kullandığınız kodu paylaşır mısınız? Bu, küçük resim oluşturucum için umut verici bir yaklaşım gibi görünüyor. Teşekkürler!
Dave

1

Phantomjs yükleyin

$ npm install phantomjs

Aşağıdaki kodla github.js dosyası oluşturun

var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
page.open('http://github.com/', function() {
    page.render('github.png');
    phantom.exit();
});

Dosyayı argüman olarak phantomjs'e iletin

$ phantomjs github.js


-3

Şunları yapabilirsiniz referans eklemek HtmlRenderer , projenize ve aşağıdakileri yapın

string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.