首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在网页中显示像手机机箱背面这样的形状(带有透明的摄像头孔)的图像?

如何在网页中显示像手机机箱背面这样的形状(带有透明的摄像头孔)的图像?
EN

Stack Overflow用户
提问于 2014-10-25 11:42:44
回答 2查看 315关注 0票数 1

我正在进行一个项目,在这个项目中,我正在开发一个网络应用程序,艺术家可以在那里上传艺术品,这些作品将被打印在各种智能手机手机上(类似RedBubble.com或Society6.com网站的一个小版本)。

因此,作为它的一个模块,我想要实现的是:

  1. 管理员可以从管理面板上传手机机箱的形状(就在机箱后面有透明的摄像头孔)。
  2. 艺术家可以上传的艺术作品,并将显示在所有可用的电话箱作为最终产品给客户。

我对此进行了大量的搜索,并提出了以下的想法,但现在我完全迷失了方向:

  1. 管理员可以使用像InkScape这样的软件创建图形,这将给他们提供SVG文件及其代码。
  2. 这些文件可以存储在数据库中(文件的内容或文件名,我无法弄清楚)。
  3. 艺术家将上传他/她的作品,并将作为jpg文件存储在数据库中。

所以现在,我有两个,形状(SVG)和艺术品(JPG)存储在数据库中。

我只是不知道如何显示最终的产品,这将是选定的艺术作品在选定的手机外壳形状SVG。还是我完全错了?

这就是我要实现的目标:

http://postimg.org/image/vp267jvp5/

但正如你所见我完全搞砸了。这是文件的代码。SVG是从InkScape生成的。我使用pattern标记来适应图像。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<body>


<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="212"
   height="360"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.5 r10040"
   sodipodi:docname="shit.svg">
  
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="1"
     inkscape:cx="76"
     inkscape:cy="265.01282"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1366"
     inkscape:window-height="691"
     inkscape:window-x="-9"
     inkscape:window-y="-9"
     inkscape:window-maximized="1"
     fit-margin-top="0"
     fit-margin-left="0"
     fit-margin-right="0"
     fit-margin-bottom="0" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1"
     style="display:inline"
     transform="translate(-299,-397.375)">
    <path
		d="m 343,397.375 c -24.376,0 -44,19.624 -44,44 l 0,272 c 0,24.376 19.624,44 44,44 l 124,0 c 24.376,0 44,-19.624 44,-44 l 0,-272 c 0,-24.376 -19.624,-44 -44,-44 l -124,0 z m 18.5,34 c 12.42641,0 22.5,6.71573 22.5,15 0,8.28427 -10.07359,15 -22.5,15 -12.42641,0 -22.5,-6.71573 -22.5,-15 0,-8.28427 10.07359,-15 22.5,-15 z"
		fill="url(#img1)"
		id="rect2985"
       inkscape:connector-curvature="0" />
  </g>
<defs>
	<filter id="blur">
  <feGaussianBlur stdDeviation="0"/>
</filter>
    <pattern id="img1" x="0" y="0" patternUnits="userSpaceOnUse" width="212"	height="360" >
        <image xlink:href="uploads/artwork.jpg" x="0" y="0" width="212" height="360"  />
    </pattern>
</defs> 
</svg>
<img src="uploads/artwork.jpg" >
</body>
</html>

如果你能给我提供一些步骤、例子或教程链接,或者我应该使用一些库,我会很感激,因为我搜索了上面的内容。我正在使用php和mysql数据库服务器。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-26 04:42:37

通过操作SVG,您可以通过以下方式实现您想要的结果:

  1. 将封面形状转换为剪辑路径。
  2. 将用户的图像动态加载到SVG中,并将剪辑路径应用到SVG中

我在这里做了一个演示小提琴。

下面是代码:

代码语言:javascript
复制
initCover("svg2", "layer1");
replaceCover("svg2", "layer1", "http://lorempixel.com/400/400/");


function  initCover(svgId, coverId)
{
    // Turn cover into a clipping path
    var svg = document.getElementById(svgId);
    var cover = svg.getElementById(coverId);
    var clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
    clipPath.setAttribute("id", "cover-clip");
    if (cover.getAttribute("transform"))
        clipPath.setAttribute("transform", cover.getAttribute("transform"));
    // Copy shape from cover to clipPath (assumes cover has only one child element
    clipPath.appendChild(cover.firstElementChild.cloneNode());
    svg.appendChild(clipPath);
    // Optionally hide the original cover shape
    cover.style.visibility = "hidden";
}


function  replaceCover(svgId, coverId, imageURL)
{
    var svg = document.getElementById(svgId);
    var cover = svg.getElementById(coverId);
    // Get the cover width and height
    var  coverBox = cover.getBBox();
    // Add a new image element for the image
    var  image = document.createElementNS("http://www.w3.org/2000/svg", "image");
    image.setAttributeNS("http://www.w3.org/1999/xlink", "href", imageURL);
    // Set image size so that the image fills the cover and is centred
    image.setAttribute("width", coverBox.width);
    image.setAttribute("height", coverBox.height);
    image.setAttribute("preserveAspectRatio", "xMidYMid slice");
    image.setAttribute("clip-path", "url(#cover-clip)");
    svg.appendChild(image);
}
票数 1
EN

Stack Overflow用户

发布于 2014-10-25 18:57:24

您可以使用html5画布的合成功能只绘制到您的手机机箱中。

特别是,context.globalCompositeOperation='source-in'只会在手机机箱的非透明像素上显示你的艺术品。

从你的手机机箱的图片开始,除了手机机箱外,所有东西都是透明的:

然后,您可以使用复合绘制您的艺术品仅在黑格像素,如:

代码语言:javascript
复制
// draw the phone case on the canvas
context.drawImage(phonecase,0,0);

// set compositing to source-in
// future drawings will only be visible where existing pixels are opaque
context.globalCompositeOperation='source-in';

// draw the artwork over the phonecase
// compositing will display the artwork only inside the opaque phonecase pixels
context.drawImage(artCanvas,offsetX,offsetY);

// always clean up! Return compositing to its default mode
context.globalCompositeOperation='source-out';

这里的示例代码和演示:

此示例增加了调整艺术品大小并将其水平和垂直重新定位的能力。

祝你的项目好运!

代码语言:javascript
复制
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var artCanvas=document.createElement("canvas");
var artCtx=artCanvas.getContext("2d");

var cw,ch,phone,art;

$scaleslider=$('#scaleslider');
$scaleslider.change(function(){ resetScale(); draw(); })
//
$hslider=$('#hslider');
$hslider.change(function(){ draw(); })
//
$vslider=$('#vslider');
$vslider.change(function(){ draw(); });


// image preloader
var imageURLs=[];  
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/case.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/art.png");
// the loaded images will be placed in imgs[]
var imgs=[];
var imagesOK=0;
loadAllImages(start);

function loadAllImages(callback){
  for (var i=0; i<imageURLs.length; i++) {
    var img = new Image();
    imgs.push(img);
    img.onload = function(){ 
      imagesOK++; 
      if (imagesOK>=imageURLs.length ) {
        callback();
      }
    };
    img.onerror=function(){alert("image load failed");} 
    img.crossOrigin="anonymous";
    img.src = imageURLs[i];
  }      
}
//
function start(){
  // the imgs[] array now holds fully loaded images

  // user friendly names for images
  phone=imgs[0];
  art=imgs[1];

  // size the on-screen canvas to phone size
  cw=canvas.width=phone.width;
  ch=canvas.height=phone.height;

  // resetScale
  resetScale();
  // draw the initial rendering
  draw();
}

function resetScale(){
  var scale=$scaleslider.val()/100;

  // calc the scaled size of the artwork
  var artW=art.width*scale;
  var artH=art.height*scale;
  // size the off-screen canvas to allow 2x2 of art images   
  artCanvas.width=artW*2;
  artCanvas.height=artH*2;
  // draw a grid of 2x2 art images to allow horizontal
  // and vertical repositioning
  artCtx.drawImage(art,0,0,artW,artH);
  artCtx.drawImage(art,artW,0,artW,artH);
  artCtx.drawImage(art,artW,artH,artW,artH);
  artCtx.drawImage(art,0,artH,artW,artH);
  // set offsets used in horiz & vert repositioning
  $hslider.attr('max',artW);
  $hslider.val(0);
  $vslider.attr('max',artH);
  $vslider.val(0);    
}

// draw the artwork inside the phone case
// Use the slider values to reposition the artwork
function draw(){
  var offsetX=-$hslider.val();
  var offsetY=-$vslider.val();
  ctx.clearRect(0,0,cw,ch);
  ctx.save();
  ctx.drawImage(phone,0,0);
  ctx.globalCompositeOperation='source-in';
  ctx.drawImage(artCanvas,offsetX,offsetY);
  ctx.restore();
}
代码语言:javascript
复制
body{ background-color: ivory; }
canvas{border:1px solid red;}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Scale Artwork<input id=scaleslider type=range min=25 max=150 value=100><br>
Move Horizontally:<input id=hslider type=range min=0 max=200 value=100><br>
Move Vertically:<input id=vslider type=range min=0 max=200 value=100><br>
<canvas id="canvas" width=300 height=300></canvas>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26561970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档