问题
I'm working on adding some very basic jQuery to my website. I want to explode an image of some balloons when it's clicked. I tried adding a height to the section as suggested in the answer to another question but it still doesn't work...
Other effects I try on it, like fadeOut, work fine...
Please help!
script.js:
//fadeIn blue flower
$(document).ready(function(){
$('#blue_flower').hide().fadeIn('slow');
});
//fadeOut clover
$(document).ready(function(){
$('#four_leaf_clover').click(function(){
$(this).fadeOut('slow');
});
});
//explode baloons
$(document).ready(function(){
$('#balloons').click(function(){
$(this).hide("explode", {pieces:16}, 5000);
});
});
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Website Design and Development by Melanie Martin</title>
<meta charset="utf-8" />
<meta name="author" content="Melanie Martin" />
<meta name="description" content="Content based website design and development services." />
<meta name="keywords" content="webstie design, web design, web development, kansas city, Melanie Martin" />
<script src="jquery-1.9.1.min.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="baseline.css" type="text/css" />
<link rel="stylesheet" href="template.css" type="text/css" />
<!--lets older browsers see the cool new html5 tags-->
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<section id="CorkBoard" class="leftsection">
<section class="oi">
<section id="Melanie_photo">
<a href="about.html"><img class="melanie_photo" src="images/melanie.png" alt="Melanie Martin" /></a>
</section>
<section id="blue_flower">
<img id="blue_flower" src="images/blue_flower.png" alt="Click the flower!" />
</section>
<section id="business_card">
<a href="contact.html"><img class="business_card" src="images/business_card.png" alt="Contact Melanie Martin" /></a>
</section>
<section id="four_leaf_clover">
<img id="four_leaf_clover" src="images/four_leaf_clover.png" alt="Click the clover!" />
</section>
<section id="balloons">
<img id="balloons" src="images/baloons.png" alt="Click the balloons!" />
</section>
<!--<section id="html5_badge">
<a href="http://www.w3.org/html/logo/"><img src="http://www.w3.org/html/logo/badge/html5-badge-h-solo.png" width="63" height="64" alt="HTML5 Powered" title="HTML5 Powered"></a></a>
</section>-->
<!--<section id="weather_widget">
</section>
<ul>
<li>Weather gadget</li>
<li>Lock with "code" as the combo (will link to code samples)</li>
<li>Blue ribbon with W3C Validated on it (with W3C link)</li>
<li>Stationary "Special Deals" link / emblem</li>
<li>Contact Me Button</li>
<li>Drawing of Lilo</li>
<li>
</ul>-->
</section>
</section>
<section id="DryEraseArea" class="rightsection">
<section class="oi">
<nav id="PostIt">
<nav class="oi">
<section id="pink_post-it" class="post-it"><a href="index.html"><img src="images/pink-up.png" alt="Home Page" ></a></section>
<section id="blue_post-it" class="post-it"><a href="projects.html"><img src="images/blue-down.png" alt="Projects Page"></a></section>
<section id="green_post-it" class="post-it"><a href="about.html"><img src="images/green-down.png" alt="About Melanie Martin"></a></section>
<section id="purple_post-it" class="post-it"><a href="contact.html"><img src="images/purple-down.png" alt="Contact Melanie Martin"></a></section>
</nav>
</nav>
<section id="DryErase" class="rightsection">
<section class="oi">
<h1>Woohoo! You made it here!</h1>
<p>Hooray! You found the site where Melanie shows off all her cool projects and recent freelance work! Take a look around the site<!--, read some articles,--> and let us know what you think.</p>
<h2>Melanie Offers Freelance Services in a Variety of Areas</h2>
<h3>Website Design</h3>
<p>Melanie specializes in content centered design. Nothing is more important than the message you want to convey to your visitors. That's why she starts with your articles and images and builds a custom website around them. The site is just the pretty packaging that shows off all your cool stuff.</p>
<h3>Social Media Integration</h3>
<p>Add social media like Facebook, Twitter, LinkedIn, Stumble, Reddit and others to your site to increase traffic and make the most of your advertising budget. Social media also gets your visitors involved and benefits your search engine ranking.</p>
<h3>Website Redesign</h3>
<p>An outdated site can put visitors off and give your company a poor image. Melanie recommends taking a fresh look at your current site at least once every three years. Sometimes an entire redesign is needed but often just a little "face lift" can get you the results you need.</p>
<h3>Website Maintenance & Monitoring</h3>
<p>Melanie offers solutions for all your web needs. When you don't have the time or desire to update content, deal with host issues like setting up users and email addresses, and monitor your sites traffic, she can customize a plan to take care of it for you. There's no need to worry because she can cover it all. </p>
<h3>Free Consultations</h3>
<p>Consultations are always free. Whether it's a large or small project doesn't matter just give us a shout and we'll give you free advice, recommendations, or estimates.</p>
</section>
</section>
</section>
</section>
<footer class="oi">
<section>
<!--<p>Copyright bagdge goes here.</p>-->
</section>
</footer>
</body>
</html>
template.css:
/*Cork Background*/
html {
background:tan;
background-image:url(images/corkboard.jpg);
min-width:1100px;
max-width:1400px;
padding:none;
margin:none;
border:none;
}
@font-face {
font-family: popstarAutograph;
src: url(popstarAutograph.otf);
}
h2 {
font-family:popstarAutograph;
font-weight:bold;
}
#DryErase .oi {
font-family:popstarAutograph;
font-weight:bold;
color:navy;
font-size:2em;
line-height:1.125;
}
/*Cork Board Area*/
#CorkBoard {
float:left;
width:33%;
min-width:325px;
}
#CorkBoard .oi {
min-height:+VALUE;
margin:+VALUE;
padding:+VALUE;
background:VALUE;
border:VALUE;
}
#CorkBoard img {
margin:20px;
}
#business_card {
float:right;
}
#html5_badge {
margin:100px 0 0 0;
}
#blue_flower {
height:130px;
width:100px;
float:right;
}
#four_leaf_clover {
height:30px;
width:25px;
float:left;
}
section #balloons{
height:500px;
width:350px;
border:5px solid;/*added for debugging*/
}
#balloons img{
height:200px;
width:175px;
float:right;
border:5px solid;/*added for debugging*/
}
/*Post-it and Dry Erase Board*/
#DryEraseArea {
float:right;
width:66%;
min-width:720px;
}
#DryEraseArea .oi {
min-height:+VALUE;
margin:+VALUE;
padding:+VALUE;
background:VALUE;
}
/*Dry Erase Post-it Menu*/
#PostIt {
float:VALUE;
min-width:720px;
height:140px;
max-height:140px;
}
#PostIt .oi {
min-height:+VALUE;
margin:+VALUE;
padding:+VALUE;
background:plum;
}
.post-it img {
height:140px;
width:;
float:left;
}
#pink_post-it img {
margin-left:20px;
margin-top:;
}
/*Dry Erase Board Area */
#DryErase {
float:VALUE;
}
#DryErase .oi {
min-height:+VALUE;
margin-top:-42px;
padding:25px 35px 35px 35px;
background:white;
border-radius:15px;
border:VALUE;
}
/*Contact Page*/
#contactpostit {
width:150px;
float:right;
}
/*Projects Page*/
#projects {
margin:0 25px 0 25px;
}
#projects img{
vertical-align:text-top;
margin:-35px 10px 75px 10px;
width:250px;
}
/*Contact*/
#contact #contactpostit {
float:right;
margin:45px 15px 15px 15px;
width:150px;
}
/*Footer*/
footer {
float:VALUE;
width:100%;
min-width:VALUE;
max-width:VALUE;
}
footer .oi {
min-height:+VALUE;
margin:+VALUE;
padding:+VALUE;
background:VALUE;
clear:both;
}
回答1:
Like several other hide
effects, you need jQuery UI to add the explode
effect:
Add this to your script
tags:
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
See jQuery UI effects.
回答2:
I made a jquery plugin for exploding image. It uses canvas for effecting. https://github.com/blackmiaool/jquery-image-explode
And its source code here: (recommend browsing it on github)
//github https://github.com/blackmiaool/jquery-image-explode
(function ($) {
"use strict";
const wrapperName = "explode-wrapper";
if(!$){
console.error("jQuery is needed.");
return;
}
$.fn.explodeRestore = function () {
this.each(function () { //explode separately
const $dom = $(this);
const wrapper = $dom.prop(wrapperName);
if (wrapper) {
wrapper.replaceWith($dom);
$dom.prop(wrapperName, null);
}
});
};
$.fn.explode = function (opt) {
if (!opt || typeof opt !== "object") {
opt = {};
}
const {
minWidth = 3,
omitLastLine = false,
radius = 80,
minRadius = 0,
release = true,
fadeTime = 300,
recycle = true,
recycleDelay = 500,
fill = true,
explodeTime = 300,
maxAngle = 360,
gravity = 0,
round = false,
groundDistance = 400,
ignoreCompelete = false,
land=true,
checkOutBound,
finish,
} = opt;
let {
maxWidth
} = opt;
const $target = this;
let $targetImage;
const args = arguments;
if ($target.length > 1) { //explode separately
$target.each(function () {
const $dom = $(this);
$dom.explode.apply($dom, args);
});
return;
} else if (!$target.length) {
return;
}
if ($target.prop("tagName") === "IMG") {
if (!$target.prop("complete")) {
$target.on("load", function () {
$target.explode.apply($target, args);
});
return;
}
$targetImage = $target;
} else if ($target.css("backgroundImage") !== "none") {
const src = $target.css("backgroundImage").match(/url\(\"([\S\s]*)\"\)/)[1];
$targetImage = $("<img/>", {
src
});
if (!opt.ignoreCompelete) {
$targetImage.on("load", function () {
opt.ignoreCompelete = true;
$target.explode.apply($target, [opt]);
});
return;
}
}
const w = $target.width();
const h = $target.height();
const minorDimension = Math.min(w, h);
const radiusData = getRadiusData();
const ctxWidth = Math.max(w, radius * 2);
const ctxHeight = Math.max(h, radius * 2, groundDistance * 2);
if (!maxWidth) {
maxWidth = minorDimension / 4;
}
const $wrapper = $("<div></div>", {
"class": wrapperName,
});
const syncStyles = ["width", "height", "margin-top", "margin-right", "margin-bottom", "margin-left", "position", "top", "right", "bottom", "left", "float", "display"];
syncStyles.forEach((v) => {
$wrapper.css(v, $target.css(v));
});
// $wrapper.css("background-color", "black");
if ($wrapper.css("position") === "static") {
$wrapper.css("position", "relative");
}
const startRatio = 0.3;
//generate rags' body
const rags = generateRags();
getRagsFinalState();
const $canvas = $("<canvas></canvas>");
//standard canvas, to draw the ideal target
const $canvas0 = $("<canvas></canvas>");
$canvas0.css({
width: w,
height: h,
});
$canvas0.attr({
width: w,
height: h,
});
$canvas.css({
position: "absolute",
left: (w - ctxWidth) / 2,
right: (w - ctxWidth) / 2,
top: (h - ctxHeight) / 2,
bottom: (h - ctxHeight) / 2,
margin: "auto",
width: ctxWidth,
height: ctxHeight,
});
$canvas.attr({
width: ctxWidth,
height: ctxHeight,
});
$wrapper.append($canvas);
const ctx = $canvas[0].getContext("2d");
const ctx0 = $canvas0[0].getContext("2d");
const {
naturalWidth,
naturalHeight
} = $targetImage?$targetImage[0]:{};
if ($target.prop("tagName") === "IMG") {
ctx0.drawImage($targetImage[0], 0, 0, naturalWidth, naturalHeight, 0, 0, w, h);
} else if ($target.css("backgroundImage") !== "none") {
let dx = 0,
dy = 0,
dWidth = naturalWidth,
dHeight = naturalHeight;
let config = {
'background-repeat': $target.css("background-repeat"),
"background-size": $target.css("background-size"),
'background-position-x': $target.css("background-position-x"),
'background-position-y': $target.css("background-position-y"),
}
function warn(key) {
console.warn(`Unsupported ${key} style:${config[key]}`);
}
const ratioW = w / naturalWidth;
const ratioH = h / naturalHeight;
if (config["background-size"] === "cover") {
const ratio = Math.max(ratioW, ratioH);
dWidth = naturalWidth * ratio;
dHeight = naturalHeight * ratio;
} else if (config["background-size"] === "contain") {
const ratio = Math.min(ratioW, ratioH);
dWidth = naturalWidth * ratio;
dHeight = naturalHeight * ratio;
} else {
warn("background-size");
}
dx = parseInt(config['background-position-x']) / 100 * (w - dWidth);
dy = parseInt(config['background-position-y']) / 100 * (h - dHeight);
if (config["background-repeat"] === "repeat") {
for (var i = 0 - Math.ceil(dx / dWidth); i < w / dWidth + Math.ceil(-dx / dWidth); i++) {
for (var j = 0 - Math.ceil(dy / dHeight); j < h / dHeight + Math.ceil(-dy / dHeight); j++) {
ctx0.drawImage($targetImage[0], 0, 0, naturalWidth, naturalHeight, dx + i * dWidth, dy + j * dHeight, dWidth, dHeight);
}
}
} else if (config["background-repeat"] === 'no-repeat') {
ctx0.drawImage($targetImage[0], 0, 0, naturalWidth, naturalHeight, dx, dy, dWidth, dHeight);
} else {
warn("background-repeat");
}
} else if ($target.css("backgroundColor") !== "rgba(0, 0, 0, 0)") {
ctx0.fillStyle = $target.css("backgroundColor");
ctx0.fillRect(0, 0, w, h);
} else {
console.warn("There's nothing to explode.");
}
const scaleX = 1;
const scaleY = 1;
rags.forEach((rag) => {
const {
left,
top,
width: ragWidth,
height: ragHeight,
} = rag;
rag.naturalParams = [left, top, ragWidth, ragHeight];
});
$target.after($wrapper);
$target.prop(wrapperName, $wrapper);
$target.detach();
let biasVy = 0;
explode(function () {
if (release) {
doRelease();
} else if (recycle) {
doRecycle();
}else{
finish&&finish();
}
});
function doRelease(cb) {
const startTime = Date.now();
let leftCnt = rags.length;
rags.forEach((rag) => {
rag.time1 = 1000 / (rag.ratio * (maxWidth + 1 - rag.width) / maxWidth + 0.1);
rag.time2 = rag.time1 + fadeTime;
});
draw();
function draw() {
const time = Date.now();
const duration = time - startTime;
ctx.clearRect(0, 0, ctxWidth, ctxHeight);
rags.forEach((rag) => {
ctx.save();
const {
width: ragWidth,
height: ragHeight,
} = rag;
ctx.translate(rag.biasx, rag.biasy);
ctx.rotate(rag.lastAngle || rag.finalAngleRad);
if (round) {
ctx.beginPath();
ctx.arc(0, 0, ragWidth / 2, 0, Math.PI * 2, false);
ctx.closePath();
ctx.clip();
}
let alpha;
if (duration < rag.time1) {
alpha = 1;
} else if (duration > rag.time2) {
alpha = 0;
} else {
alpha = 1 - (duration - rag.time1) / fadeTime;
}
if (alpha === 0 && !rag.released) {
rag.released = true;
leftCnt--;
}
ctx.globalAlpha = alpha;
ctx.drawImage($canvas0[0], rag.left, rag.top, rag.width, rag.height, -ragWidth / 2, -ragHeight / 2, ragWidth, ragHeight);
ctx.restore();
});
if (!leftCnt) {
cb && cb();
} else {
window.requestAnimationFrame(draw);
}
}
}
function doRecycle() {
setTimeout(function () {
explode(function () {
$target.explodeRestore();
}, true);
}, recycleDelay);
}
function explode(cb, reverse) {
const startTime = Date.now();
let lastTime = startTime;
let leftCnt = rags.length;
if (!reverse) {
rags.forEach((rag) => {
rag.vx = rag.translateX / explodeTime * 1000;
rag.vy = rag.translateY / explodeTime * 1000;
rag.biasx = rag.translateX0;
rag.biasy = rag.translateY0;
if (gravity) {
rag.transYMax = ctxHeight / 2 + groundDistance - rag.height / 2;
}
});
}
draw();
function draw() {
const time = Date.now();
let ratio;
let angleRatio;
ratio = (time - lastTime) / 1000;
angleRatio = (time - startTime) / explodeTime;
if (reverse) {
angleRatio = 1 - angleRatio;
}
if (gravity) {
biasVy += (gravity * ratio) * 300;
} else {
if (angleRatio > 1 || angleRatio < 0) {
cb && cb();
return;
}
ratio *= Math.cos(angleRatio * Math.PI / 2) * Math.PI / 2;
}
if (reverse) {
ratio = -ratio;
}
lastTime = time;
ctx.clearRect(0, 0, ctxWidth, ctxHeight);
rags.forEach((rag) => {
ctx.save();
const {
width: ragWidth,
height: ragHeight,
} = rag;
if (!rag.land) {
rag.biasx += rag.vx * ratio;
rag.biasy += (rag.vy + biasVy) * ratio;
if (gravity) {
if (checkOutBound && checkOutBound(rag)
|| rag.biasy > rag.transYMax
|| rag.biasy < rag.height/2) {
leftCnt--;
rag.land = true;
rag.lastAngle = rag.finalAngleRad * angleRatio;
if(land){
rag.biasy = gravity>0?rag.transYMax:rag.height/2;
}else{
rag.biasy=rag.transYMax*2;//hide
}
}
}
}
ctx.translate(rag.biasx, rag.biasy);
if (rag.lastAngle) {
ctx.rotate(rag.lastAngle);
} else {
ctx.rotate(rag.finalAngleRad * angleRatio);
}
if (round) {
ctx.beginPath();
ctx.arc(0, 0, ragWidth / 2, 0, Math.PI * 2, false);
ctx.closePath();
ctx.clip();
}
ctx.drawImage($canvas0[0], rag.left, rag.top, rag.width, rag.height, -ragWidth / 2, -ragHeight / 2, ragWidth, ragHeight);
ctx.restore();
});
if (gravity && !leftCnt) {
cb();
} else {
window.requestAnimationFrame(draw);
}
}
}
function random(min, max) {
return parseInt(Math.random() * (max + 1 - min), 10) + min;
}
//generate final position and angle of rags
function getRagsFinalState() {
rags.forEach((v, i) => {
const finalAngle = (((Math.random() * maxAngle * 2) - maxAngle) / ((Math.random() + 2) * v.width)) * 10;
//coordinate based on center point
let x = v.left + v.width / 2 - w / 2;
let y = v.top + v.width / 2 - h / 2;
if (x === 0) {
x = i % 2 ? -1 : 1;
}
if (y === 0) {
y = (i % 4 < 2) ? -1 : 1;
}
const distance = Math.sqrt(x * x + y * y);
let ratio = ((1 - startRatio) * (1 - (v.width - minWidth) / (maxWidth - minWidth)) + startRatio) * Math.random();
ratio = 1 - (1 - ratio) * (1 - minRadius / radius);
const finalDistance = (radius - distance) * ratio + distance;
const distanceSquare = distance * distance;
const attach = {
finalDistance,
ratio,
x,
y,
distance,
translateX: (finalDistance - distance) * Math.sqrt((distanceSquare - y * y) / (distanceSquare)) * (x > 0 ? 1 : -1),
translateY: (finalDistance - distance) * Math.sqrt((distanceSquare - x * x) / (distanceSquare)) * (y > 0 ? 1 : -1),
translateX0: (ctxWidth - w) / 2 + v.left + v.width / 2,
translateY0: (ctxHeight - h) / 2 + v.top + v.height / 2,
finalAngle,
finalAngleRad: finalAngle * (Math.PI / 180),
};
for (let i in attach) {
v[i] = attach[i];
}
});
}
//generate inital position and dimension of rags
//rewrite it to fit for you demand
function generateRags() {
let rowCnt;
const base = [[0, 1], [1, 1], [1, 0], [0, 0]];
if (omitLastLine) {
rowCnt = Math.floor(h / maxWidth);
} else {
rowCnt = Math.ceil(h / maxWidth);
}
const rags = [];
const noRadius = radiusData.every(function (v) {
return v === 0
});
for (let row = 0; row < rowCnt; row++) {
generateRow(row);
}
function isInner(x, y) {
if (x < radiusData[0] && y > h - radiusData[0] ||
x > w - radiusData[1] && y > h - radiusData[1] ||
x > w - radiusData[2] && y < radiusData[2] ||
x < radiusData[3] && y < radiusData[3]) {
return false;
}
return true;
}
function distanceLessThan(x1, y1, x2, y2, d) {
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < d * d;
}
function tryPushRag({
left,
top,
width,
height
}) {
const x = left + width / 2;
const y = h - top - height / 2;
if (noRadius || isInner(x, y) || radiusData.some(function (v, i) {
return distanceLessThan(x, y, base[i][0] * w + 2 * (0.5 - base[i][0]) * v, base[i][1] * h + 2 * (0.5 - base[i][1]) * v, v);
})) {
rags.push({
left,
top,
width,
height
});
}
}
function generateRow(row) {
let rowSum = 0;
const topBase = row * maxWidth;
function generate(width) {
const left = rowSum;
rowSum += width;
tryPushRag({
left,
top: topBase,
width,
height: width,
});
if (fill) {
for (let i = 1; i < parseInt(maxWidth / width); i++) {
tryPushRag({
left,
top: topBase + i * width,
width,
height: width,
});
}
}
}
let width;
do {
if (width) {
generate(width);
}
width = random(minWidth, maxWidth);
} while (w > rowSum + width);
if (w - rowSum >= minWidth) {
generate(w - rowSum);
}
}
rags.sort(function (rag1, rag2) {
return Math.random() > 0.5 ? 1 : -1;
});
return rags;
}
//get an array of 4 corners of radius
function getRadiusData() {
let ret = ["border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius"];
const width = $target.width();
ret = ret.map(function (key) {
let radius = $target.css(key);
if (radius.match(/px$/)) {
return radius.match(/^\d+/)[0] * 1;
} else if (radius.match(/%$/)) {
return radius.match(/^\d+/)[0] / 100 * width;
}
return radius;
});
ret = ret.map(function (radius) {
if (radius > width / 2) {
radius = width / 2
}
return radius;
});
return ret;
}
};
})(window.jQuery);
来源:https://stackoverflow.com/questions/15468175/jquery-image-doesnt-explode