可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to load records using breeze. While loading record i am showing spin icon. But somehow spin icon seems to stop while records are being loaded in grid.
Here is my html
<div id="showSpin" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top:248px;left: 320px; background-color: #FFF; opacity: 0.9; filter: alpha(opacity=90);">
<img src="/images/spin.gif" />
</div>
here is my code to load image
isSpinning(true)
context.getData(name, records).then(function (data) {
isSpinning(false);
setTimeout(function () {
isSpinning(false);
}, 300);
})
.fail("Record not found");
Update1
I tried below code as per answer but nothing happens. I also included css. But cant see anything.
<div id="loading" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top:240px;left: 280px; background-color: #FFF; opacity: 0.9; filter: alpha(opacity=90);">
<i class="icon-spin " style="width: 40px"></i>
<!--<img src="../../../../../Content/images/download.jpg" style="width: 40px" />-->
</div>
回答1:
This is happening because a Gif requires the thread to be open to display the next image. If you were using a pure css approach you would not see this issue. Take font-awesome for example -
<i class="icon-spin icon-spinner"></i>
Because this is a pure CSS approach the spinner will continue to spin even when the thread bogs down loading all of of your new records and associating their related entities.
If you need to continue spinning I would highly including this bit of CSS from the Font-Awesome source -
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg); }
100% {
-moz-transform: rotate(359deg); } }
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg); }
100% {
-webkit-transform: rotate(359deg); } }
@-o-keyframes spin {
0% {
-o-transform: rotate(0deg); }
100% {
-o-transform: rotate(359deg); } }
@-ms-keyframes spin {
0% {
-ms-transform: rotate(0deg); }
100% {
-ms-transform: rotate(359deg); } }
@keyframes spin {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(359deg); } }
.icon-spin {
display: inline-block;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear; }
And using either a static icon, image or sprite and just applying class of 'icon-spin' to it, regardless of whether it is an icon or not.
Edit
Add this wherever you are declaring your CSS -
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
Change this -
<div id="showSpin" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top:248px;left: 320px; background-color: #FFF; opacity: 0.9; filter: alpha(opacity=90);">
<img src="/images/spin.gif" />
</div>
to this -
<div id="showSpin" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top:248px;left: 320px; background-color: #FFF; opacity: 0.9; filter: alpha(opacity=90);">
<i class="fa fa-spinner fa-spin"></i>
</div>
The reason it is fa
instead of icon
is the current version of FontAwesome changed to use fa instead of icon due to collisions
Last Edit
Your problem now is that your logic is faulty. I have tried to explain this in comments but I will give one last update with EXACTLY how your logic should look if you want to show your spinner and have it spinning.
isSpinning(true)
context.getData(name, records).then(function (data) {
isLoading(false);
setTimeout(function () {
isSpinning(false);
}, 1000);
})
.fail("Record not found");
<div id="showSpin" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top:248px;left: 320px; background-color: #FFF; opacity: 0.9; filter: alpha(opacity=90);">
<!-- THERE IS NO REASON TO USE A VISIBLE BINDING HERE AND ON THE PARENT -->
<i class="fa fa-2x fa-spinner fa-spin"></i>
</div>
The reason this wasn't working is in your logic. Copy this EXACTLY to your solution and it will work.
回答2:
You could also Base64 encode the graphic and apply this loading graphic via CSS thus making subsequent usage faster and saving HTTP requests. The result of doing the Base64 encoded animated loader, is that for small common reusable assets like a loading or processing assets, it is already available and will continue to animate while performing numerous AJAX / HTTP requests, which is what you are trying to solve here.
See Also:
In this way, you can have the graphic loaded when the CSS is loaded. Because having Base64 encoded images in not exactly the most maintainable solution you could use a technology like SASS / Compass and use the path to an asset and then when you pre-process or compile to css it uses the path to the asset or resource and encodes it to a Base64 encoded version for you. This technique will work with all kinds of image formats etc..
Sass / Compass Base64 References:
- http://www.alwaystwisted.com/post.php?s=2013-11-23-sass-and-base64-images
- http://compass-style.org/reference/compass/helpers/inline-data/
"Embeds the contents of an image directly inside your stylesheet,
eliminating the need for another HTTP request. For small images, this
can be a performance benefit at the cost of a larger generated CSS
file"
But beware! Base64 encoding it isn't without some caveats
hard to maintain and update: without some tool to help, manually
editing and putting together image sprites is quite a chore
increased memory consumption (possibly very dramatic): this is often
overlooked. The time to deliver the images is decreased at the
expense of a bigger memory and CPU footprint, especially for large
sprites and sprites with a lot of whitespace.
bleedthrough: for sprites that don’t have much whitespace to separate
images, there’s an increased chance of nearby images visibly bleeding
through other elements, as in this case where bleedthrough was only
seen on iOS (but looked fine on Chrome and Safari on the desktop).
Note
Example Base64 Loading Spinner:
.genericLoader { background-image: url('data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==');
}
Working Example:
- http://jsbin.com/muyacodu/1/edit?html,css,output
When to Base64 Encode Images (and When Not To)
- http://davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/
Encoding Tools
- http://webcodertools.com/imagetobase64converter
- http://www.base64encode.org/
- http://www.opinionatedgeek.com/dotnet/tools/base64encode/
Other StackOverflow References:
- Is embedding background image data into CSS as Base64 good or bad practice?
- base64 encoded animated gif as css background?
回答3:
This is only something of a guess, but I think your record loading script is blocking the web browser by running in the main thread. This is not a desirable behaviour but fortunately this is exactly what webworkers were made for. First I recommend you read this page to get a little background then read on.
Basically you need to first move your loading code into a separate javascript file. This separate file should contain all the code to load the record, then place it in an object and post the object back to the main thread as shown bellow.
You can then invoke this code from your main thread using:
var myWorker = new Worker("my_loading_code.js");
Now the content which a webworker can directly access is limited due to thread safety concerns, therefore you may need to retrieve the records and then send them to the main thread using a postMessage(x);
call which allows you to send any object back to the main page. The main page can then react to this message by installing a message handler with:
myWorker.onmessage = function(record){
// This is only pseudo code, use your actual code here
reactToRecievingRecord(record);
};
This means that the main thread is not blocked while all the records load and can animate your icon, only blocking briefly when it receives a record.
If this is not clear enough or you need more help please just ask :)
EDIT:
To go into detail, in your case, inside the separate file you will want some code which does something along the lines of:
context.getData(name, records).then(function (data) {
postMessage(data);
})
then in your main file you want:
isSpinning(true);
var myWorker = new Worker("my_loading_code.js");
myWorker.onmessage = function(record){
// This is only pseudo code, use your actual code here
isLoading(false);
isSpinning(false);
};
Note, this code does not actually do anything with the data once it receives it, you will want to handle that but I am sure you get the rough idea. Note these are also snippets only, you will need to turn them into full functions etc