整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          刷爆朋友圈的“七彩祥云”,其實是這樣生成的

          刷爆朋友圈的“七彩祥云”,其實是這樣生成的

          /羊城派記者 陳亮

          圖/陳亮 趙思穎

          6月28日傍晚,廣州多地均可見一片七彩的云朵,猶如肥皂泡漂浮于白色的云層之間,在夕陽余暉的映照下發出絢麗多姿的光芒,持續了大約20分鐘,非常罕見且極具觀賞性。記者日前采訪了中山大學大氣科學學院副教授伊炳祺,原來,這種像彩虹一樣的美麗云霞學名叫“虹彩云”(iridescence, irisation, rainbow clouds)。

          據伊炳祺老師觀察,云中出現五顏六色的色彩,有時色彩是混合在一起的,有時則是平行帶狀出現在云的邊緣(例如云頂部)。其中,綠色和粉色較為常見。云中的虹彩最常出現在靠近太陽附近的地方,而且在太陽被遮擋住的情況下最為清晰可見,但在距離太陽較遠的地方也是可以出現的。

          圖/陳亮 趙思穎

          這種“天降祥云”的大氣現象是怎么產生的呢?伊炳祺老師指出,太陽光的衍射和干涉現象是虹彩出現的主要原因,其中在相對太陽10度角以內,衍射起主要作用;大于10度,干涉往往是主要影響因素。

          圖/陳亮 趙思穎

          伊炳祺老師進一步分析稱,這些虹彩色是扭曲了的、或破碎的華現象(同樣由于太陽光的衍射現象所引起)。在大氣中的云滴或冰晶粒子尺寸比較一致的時候,規則的華現象才會出現。

          當云發生生消變化時,這些色彩也會隨之扭曲變形或消失。高積云、卷積云,尤其是莢狀云最容易出現虹彩現象。虹彩現象也經常出現在云正在生成的時候,因為此時云滴粒子常常是具有相近的尺寸,而且此時云并不太厚。

          圖/陳亮 趙思穎

          在大家的印象中,這樣的“七彩祥云”似乎并不多見。但伊炳祺老師卻告訴記者,相比于出現在接近極地地區的貝母云(nacreous, mother-of-pearl clouds)(特殊的虹彩云),虹彩云并不算非常罕見。實際上,虹彩云在全年、各個緯度、各種天氣條件下都可以出現。尤其在炎熱、濕潤的下午天更容易出現,甚至在火箭發射飛行的尾跡云中也曾觀察到有虹彩出現。

          參考資料:

          1. https://cloudatlas.wmo.int/irisation-or-iridescence.html
          2. https://www.atoptics.co.uk/droplets/irid1.htm
          3. http://rammb.cira.colostate.edu/dev/hillger/optical-phenomena.htm

          (更多新聞資訊,請關注羊城派 pai.ycwb.com)

          來源 | 羊城派

          責編 | 江文華 實習生 | 周子厚

          | 王成

          本文轉載自SegmentFault

          WebP格式介紹

          WebP是Google開發的一種新的圖片格式,它支持有損壓縮、無損壓縮和透明度,壓縮后的文件大小比JPEG、PNG等都要小。所以可以節省帶寬,減少頁面載入時間,節省用戶的流量。

          Android和iOS的App只要引入Google提供的解碼庫,都可以很輕松的支持WebP格式。不過在Web上,WebP的支持還不是很廣泛。根據Can I Use的數據,目前只有Chrome、Opera瀏覽器,以及Android的WebView是支持WebP的。但是WebP圖片有這么多優點,我們能不能在Web頁面中使用呢?可以。這篇文章就來討論一下這個問題。

          把已有的圖片轉換為WebP格式

          要使用WebP格式,需要將你網站用到的圖片都制作一份WebP格式的版本,如果你使用CDN服務商,它們一般都會提供轉碼到WebP格式的選項。如又拍云:

          增加這樣的配置后,我們可以通過給圖片URL加上相應的后綴,來使用WebP格式的版本資源。

          你也可以使用Webpack、Gulp的插件來批量轉換圖片格式。這里不贅述。

          在瀏覽器中使用WebP格式

          因為不是所有瀏覽器都支持WebP格式,我們就有兩種思路:一個是只在支持WebP格式的瀏覽器中使用WebP格式;一個是讓不支持WebP格式的瀏覽器可以支持WebP。

          姿勢一: <Picture>標簽

          <Picture>是HTML5中的一個新標簽,類似<Video>它也可以指定多個格式的資源,由瀏覽器選擇自己支持的格式進行加載。

          <picture class="picture">

          <source type="image/webp" srcset="image.webp">

          <img class="image" src="image.jpg">

          </picture>

          如果瀏覽器支持WebP格式,就會加載Image.webp,否則會加載Image.jpg。

          即使瀏覽器不支持<Picture>標簽,圖片仍然會正常顯示,只是CSS可能無法正確選取到Picture元素。比如在IE8中,下面的CSS就不會起作用:

          .picture img { width: 100px; height: 100px;}

          但是可以這樣來給圖片寫樣式:

          .image { width: 100px; height: 100px;}

          即使瀏覽器使用的是WebP格式的圖片,最終還是會應用img元素的樣式。

          不過只要使用了HTML5Shiv,使舊的瀏覽器支持這個標簽,CSS選擇器就可以正常使用了。這種方法是最簡單的,但是不能作用于CSS中的圖片(如背景)。

          姿勢二:使用JS替換圖片的URL。

          我們有很多的頁面往往會用到圖片的“懶加載”——通常是把圖片的URL放在Img元素的一個自定義屬性中,然后用JS在適當的時機將URL賦值給SRC屬性。用類似的原理,我們可以根據瀏覽器是否支持WebP格式,給Img元素賦予不同的SRC值。

          首先我們需要用JS來判斷瀏覽器是否支持WebP格式,方法是給瀏覽器一個WebP格式的圖片,看瀏覽器能否正確渲染。這種方法是異步的,所以需要把后續的操作寫在回調函數中。我們可以將結果存儲在LocalStorage中,這樣之后就不用再次檢查了。

          function checkWebp(callback) { var img=new Image();

          img.onload=function () { var result=(img.width > 0) && (img.height > 0);

          callback(result);

          };

          img.onerror=function () {

          callback(false);

          };

          img.src='data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';

          }

          然后用下面的代碼來根據是否支持WebP替換相應的SRC。

          function showImage(useWebp){ var imgs=Array.from(document.querySelectorAll('img'));

          imgs.forEach(function(i){ var src=i.attributes['data-src'].value; if (useWebp){

          src=src.replace(/\.jpg$/, '.webp');

          }

          i.src=src;

          });

          }

          checkWebp(showImage);

          這種方式的優點是可以與已有的懶加載函數相結合。而且使用JS,我們還可以處理CSS中的圖片(如背景圖等)。

          姿勢三:使用JS解碼WebP圖片

          既然WebP的解碼器是開源的,那么能否用JS來實現呢?當然可以,有人就用JS寫出了WebP的解碼器。引入這個JS庫,就是將所有的WebP圖片用JS解碼后轉換為Base64,然后替換掉原來的URL,這樣就可以讓原本不支持WebP的瀏覽器正常顯示WebP了。這個庫的使用方法非常簡單,看網頁的說明即可。

          這種方法的缺點是,因為JS要解碼WebP圖片,需要在此異步請求SRC中的URL(不過因為圖片本身之前被下載了一次,直接使用了緩存);而且JS解碼比較慢,對性能有影響,可能需要一段時間才能顯示出圖片來。

          以上就是在瀏覽器中使用WebP圖片的幾種方法,可以根據自己的實際情況選用。在我們的實踐中,使用了WebP格式后,圖片的體積普遍縮小了1/3以上,既加快了加載的速度,還節省了用戶的流量,我們十分推薦從現在就開始使用這種格式。

          又小拍也關注WebP一段時間呢,不但關注了WebP,還關注了動態WebP,不久之后會有驚喜帶給大家哦。

          又拍云的處理功能實在太豐富,在圖片處理方面,略縮圖任意尺寸更改,全網一鍵更新所有圖片,打水印,URL防盜鏈等。最近上線的又拍直播云,除了直播加速、推拉流外,更具有豐富的美顏、濾鏡、水印、防盜鏈、鑒黃、禁播等功能,幫助直播平臺快速上線直播業務,快來試試吧~

          inIO

          MinIO 是一款高性能、分布式的對象存儲系統。它是一款軟件產品, 可以100%的運行在標準硬件上。即X86等低成本機器也能夠很好的運行MinIO。

          MinIO與傳統的存儲和其他的對象存儲不同的是:它一開始就針對性能要求更高的私有云標準進行軟件架構設計。因為MinIO一開始就只為對象存儲而設計。所以他采用了更易用的方式進行設計,它能實現對象存儲所需要的全部功能,在性能上也更加強勁,它不會為了更多的業務功能而妥協,失去MinIO的易用性、高效性。 這樣的結果所帶來的好處是:它能夠更簡單的實現具有彈性伸縮能力的原生對象存儲服務。

          MinIO在傳統對象存儲用例(例如輔助存儲,災難恢復和歸檔)方面表現出色。同時,它在機器學習、大數據、私有云、混合云等方面的存儲技術上也獨樹一幟。當然,也不排除數據分析、高性能應用負載、原生云的支持。

          在中國:阿里巴巴、騰訊、百度、中國聯通、華為、中國移動等等9000多家企業也都在使用MinIO產品。

          安裝

          使用如下命令快速安裝一個單機minio

          # 下載 minio
          wget https://dl.min.io/server/minio/release/linux-amd64/minio
          # 添加可執行權限
          chmod +x minio
          # 設置登錄minio的 access key
          export MINIO_ACCESS_KEY=minioadmin
          # 設置登錄minio的 secret key
          export MINIO_SECRET_KEY=minioadmin
          # 啟動 minio
          ./minio server /data

          安裝后使用瀏覽器訪問http://IP地址:9000,如果可以訪問,則表示minio已經安裝成功。輸入上面自定義的access key 和 secret key就可以登錄了。

          登錄右下角加號創建mybucket桶

          開放 mybucket 讀寫權限

          創建項目操作 MinIO

          <dependency>
          	<groupId>org.springframework.boot</groupId>
          	<artifactId>spring-boot-starter-thymeleaf</artifactId>
          </dependency>
          <dependency>
          	<groupId>org.springframework.boot</groupId>
          	<artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
          	<groupId>io.minio</groupId>
          	<artifactId>minio</artifactId>
          	<version>7.0.1</version>
          </dependency>
          <dependency>
          	<groupId>com.alibaba</groupId>
          	<artifactId>fastjson</artifactId>
          	<version>LATEST</version>
          </dependency>
          <dependency>
          	<groupId>org.projectlombok</groupId>
          	<artifactId>lombok</artifactId>
          	<optional>true</optional>
          </dependency>
          <dependency>
          	<groupId>commons-io</groupId>
          	<artifactId>commons-io</artifactId>
          	<version>2.6</version>
          </dependency>

          編輯配置文件application.yml修改MinIO相關配置

          
          server:
            port: 8080
          
          spring:
            application:
              name: minio-test
          
            thymeleaf:
              cache: false
          
            servlet:
              multipart:
                max-file-size: 10MB
                max-request-size: 100MB
          
          # minio 連接參數
          minio:
            endpoint: 192.168.20.111
            port: 9000
            accessKey: minioadmin
            secretKey: minioadmin
            bucketName: mybucket

          連接 MinIO 配置

          @Data
          @ConfigurationProperties(prefix="minio")
          @Component
          public class MinioProp {
          	private String endpoint;
          	private String accesskey;
          	private String secretKey;
          	private int port;
          }

          創建 MinioClient

          @Component
          public class MinioConfiguration {
          
          	@Autowired
          	private MinioProp minioProp;
          
          	@Bean
          	public MinioClient minioClient() throws InvalidPortException, InvalidEndpointException {
          		//MinioClient client=new MinioClient(minioProp.getEndpoint(), minioProp.getAccesskey(), minioProp.getSecretKey());
          		MinioClient client=MinioClient.builder().endpoint(minioProp.getEndpoint(), minioProp.getPort(), false).credentials(minioProp.getAccesskey(), minioProp.getSecretKey()).build();
          		return client;
          	}
          }

          MinIO 查看桶列表,存入,刪除 操作 MinioController

          @Slf4j
          @RestController
          public class MinioController {
              @Autowired
              private MinioClient minioClient;
           
              private static final String MINIO_BUCKET="mybucket";
           
              @GetMapping("/list")
              public List<Object> list(ModelMap map) throws Exception {
                  Iterable<Result<Item>> myObjects=minioClient.listObjects(MINIO_BUCKET);
                  Iterator<Result<Item>> iterator=myObjects.iterator();
                  List<Object> items=new ArrayList<>();
                  String format="{'fileName':'%s','fileSize':'%s'}";
                  while (iterator.hasNext()) {
                      Item item=iterator.next().get();
                      items.add(JSON.parse(String.format(format, item.objectName(), formatFileSize(item.size()))));
                  }
                  return items;
              }
           
              @PostMapping("/upload")
              public Res upload(@RequestParam(name="file", required=false) MultipartFile[] file) {
                  Res res=new Res();
                  res.setCode(500);
           
                  if (file==null || file.length==0) {
                      res.setMessage("上傳文件不能為空");
                      return res;
                  }
           
                  List<String> orgfileNameList=new ArrayList<>(file.length);
           
                  for (MultipartFile multipartFile : file) {
                      String orgfileName=multipartFile.getOriginalFilename();
                      orgfileNameList.add(orgfileName);
           
                      try {
                          InputStream in=multipartFile.getInputStream();
                          minioClient.putObject(MINIO_BUCKET, orgfileName, in, new PutObjectOptions(in.available(), -1));
                          in.close();
                      } catch (Exception e) {
                          log.error(e.getMessage());
                          res.setMessage("上傳失敗");
                          return res;
                      }
                  }
           
                  Map<String, Object> data=new HashMap<String, Object>();
                  data.put("bucketName", MINIO_BUCKET);
                  data.put("fileName", orgfileNameList);
                  res.setCode(200);
                  res.setMessage("上傳成功");
                  res.setData(data);
                  return res;
              }
           
              @RequestMapping("/download/{fileName}")
              public void download(HttpServletResponse response, @PathVariable("fileName") String fileName) {
                  InputStream in=null;
                  try {
                      ObjectStat stat=minioClient.statObject(MINIO_BUCKET, fileName);
                      response.setContentType(stat.contentType());
                      response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
           
                      in=minioClient.getObject(MINIO_BUCKET, fileName);
                      IOUtils.copy(in, response.getOutputStream());
                  } catch (Exception e) {
                      log.error(e.getMessage());
                  } finally {
                      if (in !=null) {
                          try {
                              in.close();
                          } catch (IOException e) {
                              log.error(e.getMessage());
                          }
                      }
                  }
              }
           
              @DeleteMapping("/delete/{fileName}")
              public Res delete(@PathVariable("fileName") String fileName) {
                  Res res=new Res();
                  res.setCode(200);
                  try {
                      minioClient.removeObject(MINIO_BUCKET, fileName);
                  } catch (Exception e) {
                      res.setCode(500);
                      log.error(e.getMessage());
                  }
                  return res;
              }
           
              private static String formatFileSize(long fileS) {
                  DecimalFormat df=new DecimalFormat("#.00");
                  String fileSizeString="";
                  String wrongSize="0B";
                  if (fileS==0) {
                      return wrongSize;
                  }
                  if (fileS < 1024) {
                      fileSizeString=df.format((double) fileS) + " B";
                  } else if (fileS < 1048576) {
                      fileSizeString=df.format((double) fileS / 1024) + " KB";
                  } else if (fileS < 1073741824) {
                      fileSizeString=df.format((double) fileS / 1048576) + " MB";
                  } else {
                      fileSizeString=df.format((double) fileS / 1073741824) + " GB";
                  }
                  return fileSizeString;
              }
          }

          Res返回數據封裝


          @lombok.Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class Res implements Serializable {
          	private static final long serialVersionUID=1L;
          	private Integer code;
          	private Object data="";
          	private String message="";
          }

          路由文件 RouterController

          @Controller
          public class RouterController {
          	@GetMapping({"/", "/index.html"})
          	public String index() {
          		return "index";
          	}
          
          	@GetMapping({"/upload.html"})
          	public String upload() {
          		return "upload";
          	}
          }

          啟動類

          @SpringBootApplication
          @EnableAutoConfiguration
          @ComponentScan(basePackages="com.minio")
          public class ServerApplication {
          
          	public static void main(String[] args) {
          		SpringApplication.run(ServerApplication.class, args);
          	}
          
          }


          前端 列表頁面 src\main\resources\templates\index.html

          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
              <meta charset="utf-8"/>
              <title>圖片列表</title>
              <link rel="stylesheet" href="http://cdn.staticfile.org/element-ui/2.13.1/theme-chalk/index.css">
          </head>
          <body>
           
          <div id="app">
           
              <el-link icon="el-icon-upload" href="/upload.html">上傳圖片</el-link>
              <br/>
           
              <el-table :data="results" stripe style="width: 60%" @row-click="preview">
                  <el-table-column type="index" width="50"></el-table-column>
                  <el-table-column prop="fileName" label="文件名" width="180"></el-table-column>
                  <el-table-column prop="fileSize" label="文件大小"></el-table-column>
                  <el-table-column label="操作">
                      <template slot-scope="scope">
                          <a :href="'/download/' + scope.row.fileName + ''" class="el-icon-download">下載</a>
                          <a :href="'/delete/' + scope.row.fileName + ''" @click.prevent="deleteFile($event,scope.$index,results)"
                             class="el-icon-delete">刪除</a>
                      </template>
                  </el-table-column>
              </el-table>
           
              <br/>
              <el-link icon="el-icon-picture">預覽圖片</el-link>
              <br/>
              <div class="demo-image__preview" v-if="previewImg">
                  <el-image style="width: 100px; height: 100px" :src="imgSrc" :preview-src-list="imgList"></el-image>
              </div>
           
          </div>
           
          <script src="http://cdn.staticfile.org/vue/2.6.11/vue.min.js"></script>
          <script src="http://cdn.staticfile.org/axios/0.19.2/axios.min.js"></script>
          <script src="http://cdn.staticfile.org/element-ui/2.13.1/index.js"></script>
           
          <script>
              new Vue({
                  el: '#app',
                  data: {
                      bucketURL: 'http://192.168.20.111:9000/mybucket/',
                      previewImg: true,
                      results: [],
                      imgSrc: '',
                      imgList: []
                  },
                  methods: {
                      init() {
                          axios.get('/list').then(response=> {
                              this.results=response.data;
                              if (this.results.length==0) {
                                  this.imgSrc='';
                                  this.previewImg=false;
                              } else {
                                  for (var i=0; i < this.results.length; i++) {
                                      this.imgList.push(this.bucketURL + this.results[i].fileName);
                                      if (i==0) {
                                          this.imgSrc=this.bucketURL + this.results[0].fileName;
                                      }
                                  }
                              }
                          });
                      },
                      preview(row, event, column) {
                          this.imgSrc=this.bucketURL + row.fileName;
                          this.previewImg=true;
                      },
                      deleteFile(e,index,list) {
                          axios.delete(e.target.href, {}).then(res=> {
                              if (res.data.code==200) {
                                  this.$message('刪除成功!');
                                  list.splice(index, 1);
                                  this.previewImg=false;
                              } else {
                                  this.$message('刪除失敗!');
                              }
                          });
                      }
                  },
                  mounted() {
                      this.init();
                  }
              });
          </script>
           
          </body>
          </html>

          前端上傳頁面 src\main\resources\templates\upload.html

          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
              <meta charset="UTF-8">
              <title>圖片上傳</title>
              <link rel="stylesheet" type="text/css" href="http://cdn.staticfile.org/webuploader/0.1.5/webuploader.css">
              <script type="text/javascript" src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
              <script type="text/javascript" src="http://cdn.staticfile.org/webuploader/0.1.5/webuploader.min.js"></script>
          </head>
           
          <body>
           
          <div id="uploader-demo">
              <div id="fileList" class="uploader-list"></div>
              <div id="filePicker">選擇圖片</div>
          </div>
          <br/>
          <a href="/index.html">返回圖片列表頁面</a>
           
          <script type="text/javascript">
              var uploader=WebUploader.create({
                  auto: true,
                  swf: 'http://cdn.staticfile.org/webuploader/0.1.5/Uploader.swf',
                  server: '/upload',
                  pick: '#filePicker',
                  accept: {
                      title: 'Images',
                      extensions: 'gif,jpg,jpeg,bmp,png',
                      mimeTypes: 'image/*'
                  }
              });
           
              uploader.on('fileQueued', function (file) {
                  var $li=$(
                      '<div id="' + file.id + '" class="file-item thumbnail">' +
                      '<img>' +
                      '<div class="info">' + file.name + '</div>' +
                      '</div>'
                      ),
                      $img=$li.find('img');
           
                  var $list=$("#fileList");
                  $list.append($li);
           
                  uploader.makeThumb(file, function (error, src) {
                      if (error) {
                          $img.replaceWith('<span>不能預覽</span>');
                          return;
                      }
                      $img.attr('src', src);
                  }, 100, 100);
              });
           
              uploader.on('uploadProgress', function (file, percentage) {
                  var $li=$('#' + file.id),
                      $percent=$li.find('.progress span');
           
                  if (!$percent.length) {
                      $percent=$('<p class="progress"><span></span></p>')
                          .appendTo($li)
                          .find('span');
                  }
                  $percent.css('width', percentage * 100 + '%');
              });
           
              uploader.on('uploadSuccess', function (file) {
                  $('#' + file.id).addClass('upload-state-done');
              });
           
              uploader.on('uploadError', function (file) {
                  var $li=$('#' + file.id),
                      $error=$li.find('div.error');
           
                  if (!$error.length) {
                      $error=$('<div class="error"></div>').appendTo($li);
                  }
                  $error.text('上傳失敗');
              });
           
              uploader.on('uploadComplete', function (file) {
                  $('#' + file.id).find('.progress').remove();
              });
          </script>
           
          </body>
          </html>

          運行項目


          列表頁面

          參考博客:

          https://blog.csdn.net/jianzhang11/article/details/105672261


          主站蜘蛛池模板: 日本亚洲国产一区二区三区| 无码精品不卡一区二区三区| 免费观看一区二区三区| 午夜福利av无码一区二区| 在线不卡一区二区三区日韩| 无码国产精品一区二区免费模式| 精品成人乱色一区二区| 国产成人无码精品一区在线观看| 2018高清国产一区二区三区| 中文字幕一区二区人妻| 亚洲国产精品一区二区九九| 国产一区二区好的精华液| 91久久精品无码一区二区毛片| 香蕉视频一区二区| 日本丰满少妇一区二区三区| 欧美日韩综合一区二区三区| 久久精品黄AA片一区二区三区 | 无码精品视频一区二区三区| 国产成人无码精品一区不卡| 国产丝袜美女一区二区三区| 秋霞电影网一区二区三区| 精品爆乳一区二区三区无码av| 鲁丝片一区二区三区免费| 精品国产一区二区三区久久蜜臀 | 一夲道无码人妻精品一区二区| 精品视频一区二区观看| 国产精品熟女视频一区二区 | 97久久精品午夜一区二区 | 国产精品区AV一区二区| 色综合视频一区二区三区 | 国产vr一区二区在线观看| 国产精品伦一区二区三级视频 | 中文字幕VA一区二区三区| 福利一区福利二区| 国产MD视频一区二区三区| 一区二区三区免费在线视频| 性盈盈影院免费视频观看在线一区 | 亚洲国产一区国产亚洲| 一区二区三区四区免费视频| 亚洲国产欧美一区二区三区| 无码人妻精品一区二区三区夜夜嗨|