Kurt Hsu's blog

The Rails developer in taiwan.


  • 首頁

  • 標籤

  • 分類

  • 歸檔

[Rails]簡易操作自己的model migration schema

發表於 2018-04-13 更新於 2019-08-21 分類於 Rails

本篇只是嘗試著練習及把玩model migrate schema的新增修改以及刪除

參考文章
Rails實戰聖經
Ruby on Rails 指南手冊

介紹

model
可以建立表單相依性和建立商業邏輯等等的地方

migration
在Rails裡可以操作資料庫的檔案-搭配rake執行任務

schema
資料庫綱要-通常由migration執行任務去控制千萬不要直接去改動它


正常的建立model和資料庫表單

最終會得到:
1.新的model
2.新的migration
3.更新schema

通常一次性的建立model和要在資料庫建立table使用以下指令
$ rails g model car

螢幕快照 2018-04-13 下午9.17.00.png

我們建立了
car 的 model
app/models/car.rb
create car的migration
db/migrate/xxxxxxxxxxxxx_create_cars.rb

這時候我們會去更新db/migrate/xxxxxxxxxxxxx_create_cars.rb這隻檔案賦予他等等建立這個表單有什麼項目,最後執行$ rake db:migrate更新資料庫綱要schema.rb並且在資料庫建立這個表單


刪除model

$ rails destroy model car


修改資料庫表單

通常一個表單不會一次建立好,例如我們要去修改剛剛car的這個表單要如何實作?
例如想在表單內新增車的顏色欄位
$ rails g migration add_car_color
找到那隻檔案並修改

1
2
3
4
5
class AddColorToCar < ActiveRecord::Migration[5.0]
def change
add_column :car, :color, :string
end
end

注意這裡是單數
最後下指令更新資料庫表單和綱要
$ rake db:migrate
其他方法可以參考Rails實戰聖經

最後可以去查看schema.rb是否更新了


刪除資料庫表單

一樣利用migration
$ rails g migration drop_car
找到那隻檔案並修改

1
2
3
4
5
class AddColorToCar < ActiveRecord::Migration[5.0]
def change
drop_table :cars
end
end

注意這裡是複數
最後下指令更新資料庫表單和綱要
$ rake db:migrate
最後可以去查看schema.rb是否更新了


Git的補充

狀況1:取消已追蹤的所有修改$ git checkout . 單隻檔案 $ git check —<filename>
狀況2:刪除未追蹤的所有檔案$ git clean -f
狀況3:取消不小心git add .的所有檔案$ git reset單隻檔案$ git reset filename

特殊狀況:
如果已經migrate到資料庫裡面了,千萬不要以為還原檔案包括schema.rb就好了唷!
我們還是要創造一隻migration把資料庫的表單做更新之後才可以把這些檔案還原。

舉例來說我創造了car表單並且migrate到資料庫裡面了,這時候即使我把所有檔案還原並且也把schema.rb還原了,我再次下rails g model car的時候他會抱錯說表單已經存在,這時候只能去rails console看看怎麼回事,然後一樣新增migration的任務去執行更新資料庫了!

[Git]Git & Github退回指定版本簡易作法

發表於 2018-04-12 更新於 2019-08-21 分類於 Github , Git

狀況1.Git退回上一個或指定commit
狀況2.Git把剛剛修改的東西全數取消
狀況3.把剛剛git add追蹤的東西取消掉
狀況4.把已推上Github的commit倒退

狀況1.Git退回上一個或指定commit


先看commit的歷史紀錄
$ git log
可以看到commit是一堆亂數
此時有兩個方法退回之前的版本

$ git reset HEAD~1
退回上一個版本
也可以2,3,4這樣看想退幾步

$ git checkout 94bf1215a415070c71908536c7bd379e9fbd7675
這串亂碼是剛剛在git log裡面看到的
切過去之後他會要求你切新的分支出去

狀況2.Git把剛剛修改的東西全數取消


最簡單的指令
$ git checkout .
可以把剛剛修改過尚未紀錄準備上commit(git add)的檔案全數還原
那如果不小心git add檔案的話呢?
看狀況3

狀況3.把剛剛git add追蹤的東西取消掉


git reset
或者可以指定檔案
git reset filename

狀況4.把已推上Github的commit倒退


我們已經會在本地端的Git操控版本退回去了,但如果已經上Github的話呢?
Github只能繼續往下走不能往回走!
所以最簡單的做法就是push force

在本地端退回到想要回去的版本之後下
$ git push -f
就會把當前的版本全數覆蓋過去不論Github上面的所有版本紀錄如何
記得這是無法復原的!!請慎用

[Rails]簡單的掌握Routes

發表於 2018-04-12 更新於 2019-09-07 分類於 Rails , Routes

相信很多初學者對於Rails的RESTful路徑掌控和資料夾等等一開始感到很複雜,其實不然,善用觀察者指令rake routes即可以一覽全局!

Routes.rb
1
2
3
4
5
6
7
8
9
Rails.application.routes.draw do
resources: products

namespace :admin do
resources :products
end

root 'products#index'
end

resources會創造出關於CRUD的七大path,分別是
1.index
2.new
3.create
4.show
5.edit
6.update
7.destory
namespace可以自定義一個類別
root就是指定一進去的首頁該找view底下products這個資料夾裡的index.html.erb


resources基於上面原則通常創給resources的controller命名會是複數
例如products

$ rails g controller products
搭配model
$ rails g model product

這樣我們在define CRUD創立的變數就直覺許多

products_controller.rb
1
2
3
4
5
6
7
def index
@products = product.all
end

def show
@product = products.find(params[:id])
end


namespace可以讓網址多一層看起來像
/admin/products

並且會去找controller位於
/admin/products_controller.rb


大多時候Routes寫得多要從檔案裡看清楚路徑是很沒效率的,這時候我們在終端機下$ rake routes則會有當前的所有路徑,而且以這個資訊來看最準確!
螢幕快照 2018-04-12 上午11.31.03.png
這邊分成三個欄位

最左邊的是程式碼的path,最簡單的例子,只要加上_path就可以用於
<%= link_to (“導向這裡”, products__path) %>

中間欄位就是URL的呈現方式,:id則是這筆單自己生成的獨立編號,以edit為例
/products/:id/edit(.:format)
在網址上會成為
/products/1/edit

最右邊的欄位是他會去找哪一個controller執行,例如
products#show
他會去找
/products/products_controller.rb
裡面的
def show


最後隨著專案越來越大Routes也會成長得很快,可以利用簡單得指令過濾出想知道的Controller
$ rake routes CONTROLLER=products

參考文章:
Rails 路由全解

[Rails]淺談Strong parameters機制

發表於 2018-04-10 更新於 2019-08-21 分類於 Rails

起源為防止massive-assignment問題

在Rails有個便利的機制是將表單送出之後透過massive-assignment 的技巧直接 mapping 進 Model 裡

例如在一個簡單的表單

index.html.erb
1
2
3
4
5
<%= form_for @post do |f| %>
<%= f.text_field :title %>
<%= f.text_area :content %>
<%= f.sumbit "Submit" %>
<% end %>

在controller裡的create

post_controller.js
1
2
3
4
5
6
7
8
9
10
class PostController < ApplicationController
def create
@post = current_user.posts.build(params[:post])
if @post.save
# do something
else
# do another thing
end
end
end

就可以直接成立,但如果有心人士在DOM裡面加了額外參數並且猜對了就可以做到超出權限以外的事情,最直接的就是猜中了user 權限是用 user.is_admin 作為 boolean 值,然後直接讓自己有了admin的權限。

Rails 4 有了Strong Parameters的機制

在Rails 3 裡面其實也可以手動做簡單的防護機制,但大多人嫌麻煩或者較沒經驗的開發者沒有這個觀念,這個防護機制在許多中小型網站是被忽略掉的,自從Github被Hack了之後Rails團隊把這個機制改為必定要做了!

現在我們的params都要遵守Strong Parameters機制寫成如下

post_controller.js
1
2
3
4
5
6
7
8
9
10
11
12
def create
@event = Event.new(event_params)
@event.save

redirect_to :action => :index
end

private

def event_params
params.require(:event).permit(:name, :description)
end

其中:

  1. require會把:post這個model相關的參數給抓出來,如果根本沒有回傳:post相關參數,就會產生錯誤訊息。
  2. permit就是設定有哪些參數可以傳入,例如上面沒有寫參數,就算你從http request當中傳入,也會回傳nil當做沒東西。

從今以後外人想利用修改DOM把post出去的東西亂加料就會被過濾掉了!

參考文章:
從 Github 被 hack,談 Rails 的安全性( mass-assignment )
Rails實戰聖經
Rails 當中的 params 是什麼?

[Rails]實作套入Bootstrap&認識Asset Pipeline

發表於 2018-04-09 更新於 2019-08-21 分類於 Rails , Gem

實作套入Bootstrap


1.先在Gemfile安裝套件

Gemfile
1
gem 'bootstrap-sass'

$ bundle install

2.把總管理css的檔案改成scss即可以用scss的語法

$ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss

3.css載入這兩個官方文件敘述所需

app/assets/stylesheets/application.scss
1
2
@import "bootstrap-sprockets";
@import "bootstrap";

現在我們成功套入Bootstrap而且所有的css檔案都可以用@import的手法載入了

4.js載入這個官方文件敘述所需

app/assets/javascripts/application.scss
1
//= require bootstrap-sass/assets/javascripts/bootstrap-sprockets
  • bootstrap-sass官方文件

認識Asset Pipeline


現在隨著專案越大以及網站讀取的效要求,我們希望一個html就讀取一隻js檔案和css檔案就好,但我們也不可能把所有程式碼都擠到這兩隻檔案裡面去維護兩個有成千上萬的程式碼。

此時不只Rails有這種壓縮統整功能,在單純前端的世界webpak之類的套件都在做這種事情,而原本的Rails專案裡面的app/assets/javascripts/application.js和app/assets/stylesheets/application.css就是在做這種事情。

app/assets/javascripts/application.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
//= require bootstrap-sass/assets/javascripts/bootstrap-sprockets

載入的方法為:

//= require_tree someJSpath

app/assets/stylesheets/application.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/

@import "bootstrap-sprockets";
@import "bootstrap";

載入的方法為與剛剛的application.js雷同
如果有操作套入boostrap的動作現在application是scss不是css就可以用下面這個方式import進來:

@import “scssFilepath”

  • Ruby on Rails 實戰聖經

[Sql]認識數據庫

發表於 2017-11-18 更新於 2019-08-21 分類於 Sql

一、什麼是數據庫?

所有的檔案都會放在硬體裡面,但數據庫提供了方便的查詢(Query),和可以直接對他操作的CRUD(Create, Read, Update, Delete),成了一門學問。

數據庫的類型有很多種,最普遍的是「關係型數據庫」 (RDBMS: Relational Database Management System),又為 SQLite、MySQL、PostgreSQL是開源且免費的三種。

SQLite是Rails 開發時的默認數據庫。這種數據庫不是單獨的伺服器,一個數據庫即為一個檔案,但不適合多人同時連線使用。

MySQL是目前使用最廣泛,效能好,容易上手,線上資源最多的一種關係型數據庫,數據庫為一個伺服器,需要帳號密碼。
brew install mysql即可開始操作。

PostgreSQL經常與MySQL比較,是Heroku的默認數據庫。

Oracle 和 MS SQL Server是常用的付費資料庫,有更好的自己優化功能。

二、什麼是Schema?

Schema是存在數據庫的綱要,跟excel表單很像,每個項目對應一個欄位,可以有好幾筆資料在一個Schema裡面,比較不一樣的是需要定義這個欄位是字串、數值或者是布林值等等,也可以限定此欄位不得為空,如果一筆其一欄位不符合規定則不能寫入到Schema裡面。

三、一些SQL的標準語法

寫入資料庫:
INSERT INTO events VALUES ("RubyConf", 100);
拿取所有資料:
Event.create( :name => "RubyConf", :capacity => 100)
or
Event.all
或者可以直接在rails寫:
SELECT * FROM events;
執行時rails會幫我們編譯好剛剛上述的語法

四、什麼是ACID

ACID就是Atomicity, Consistency, Isolation, Durability是資料庫裡Transaction四個特性,那什麼是Transaction?

為了保證資料庫兩個表單互相更新資料的保證性資料庫有Transaction這個動作,最簡單的例子是A轉帳給B其實是更動了資料庫裡的兩筆資料,但如果讓程式一行一行跑則有可能發生A扣款了但B要增加戶頭金額的時候失敗,所以最好的做法是這些轉帳的動作要嘛全部成功要嘛至少一起失敗,才不會發生嚴重的商業錯誤。

Transaction裡面的動作是如何呢?

1
2
3
4
5
6
BEGIN;
INSERT INTO histories (user_id, amount) VALUES (1, -100);
INSERT INTO histories (user_id, amount) VALUES (2, 100);
UPDATE accounts SET balance=200 WHERE id=1;
UPDATE accounts SET balance=300 WHERE id=2;
COMMIT;

P.S:每个 SQL 句必须用分号 ; 代表结束。

這樣BEGIN到COMMIT之間的所有程式碼就可以達到我們想要的要嘛全部成功要嘛至少一起失敗了!

如果是跨資料庫(model):
ActiveRecord::Base.transaction do
A.save
B.save
C.save
end

接下來四個Transaction的特性可以先參考網上維基百科的解釋:

  • 原子性:一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
  • 一致性:在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。
  • 隔離性:資料庫允許多個並發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務並發執行時由於交叉執行而導致數據的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。
  • 持久性:事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。

五、SQL 语言: DDL

這裡先說一下所有關係型資料庫都是用 SQL(Structured Query Language) 語言,每一行程式碼都可以稱為SQL Query 或 SQL Statement。

DDL(Data Definition)是可以直接定義Schema的語法,請注意編碼(Encoding),PostgrSQL 可用 utf-8、MySQL 可用 utf8mb4。

打開或產生、砍掉檔案或刪除資料庫的話:

SQLite3:
sqlite3 your_db_name.db
MySQL:
mysql -u root -p
PostgreSQL:
psql <database_name>

再來我們只介紹在rails裡的操作語法
建立 Table:
CREATE TABLE events (name VARCHAR(50) NOT NULL, capacity INTEGER, date DATE);
會產生新的events表單,並新增三個字段name、capacity、date,默認是允許null值(可不填入),如有設NOT NULL則必須有值。

修改 Table:

改名:ALTER TABLE persons RENAME TO people;
新增字串:ALTER TABLE people ADD COLUMN status VARCHAR(50);
P.S:修改和移除字段SQLite3 沒有支援,要直接開心的Table把資料複製過去。

關於操作資料庫也可以使用擁有人性化介面的GUI套件。

六、SQL 语言: DML

操作數據的 SQL 就是 DML(Data Manipulation Language),也就是做 CRUD 的操作。

新增數據:

SQL:INSERT INTO events (capacity, name) VALUES (200, "JSConf");
rails:Event.create( :capacity => 200, :name => "JSConf")
也可以新增多筆:INSERT INTO events (capacity, name) VALUES (300, "COSCUP"), (300, "OSDC.TW");

查詢資料:

SQL:SELECT * FROM events;
rails:Event.all
也可以撈出指定字串:
SQL:SELECT name, capacity FROM events;
rails:Event.select(:name, :capacity).all
等同於:SELECT events.name, events.capacity FROM events;
也可以使用遞增排序:
SELECT name, capacity FROM events ORDER BY id;
or
SELECT name, capacity FROM events ORDER BY id ASC;
遞減排序:SELECT name, capacity FROM events ORDER BY id DESC;
分頁:SELECT name, capacity FROM events ORDER BY capacity

修改資料:

SQL:UPDATE events SET capacity=10;
rails:Event.update_all( :capacity => 10 )
可以用WHERE指定欄位裡指定的內容作修改:
SQL:UPDATE events SET capacity=100 WHERE name="RubyConf";
rails:Event.where( :name => "RubyConf" ).update_all( :capacity => 100)
也可以指定一個特定內容修改多個欄位:
SQL:UPDATE events SET capacity=100, name="RubyConf 2015" WHERE name="RubyConf";
rails:Event.where( :name => "RubyConf" ).update_all( :capacity => 100, :name => "RubyConf 2015" )

删除數據:

全部刪除:
SQL:DELETE FROM events;
rails:Event.delete_all
指定刪除:
SQL:DELETE FROM events WHERE name="RubyConf";
rails:Event.where( :name => "RubyConf" ).delete_all

Pakogi 第一次 meetup 講解 ETH wallet by Nic

發表於 2017-09-18 更新於 2019-08-21 分類於 生活 , 上課

最近幾乎所有的團員都有在了解區塊鏈(blockchain)這個東西,事實上它似乎也變成一個很熱門的投資項目,不過大部分的人對於虛擬幣這個東西就只知道找個交易所買賣而已,但更多基本的知識似乎還不夠多。

今天第一次meetup就由師傅兼講師的Nic Lin授課,先來看看講了些什麼囉!

冷錢包V.S熱錢包V.S交易所

先來稍微解釋什麼是錢包,如果你要買虛擬幣就需要虛擬錢包,而對一般人來說最簡單的方法就是去交易所辦一個帳號,他自然會給你虛擬錢包。

虛擬錢包使用的方法就是拿私鑰去打開公鑰,公鑰是眾所皆知的但私鑰則是必須好好小心保管的東西,一但有了錢包的私鑰和公鑰他就能直接動用裡面的錢囉!

保管私鑰的方式有很多種,那冷熱錢包的定義是如何自己如何保管私鑰的方式,所謂的熱錢包就是24小時私鑰擺放的地方都是與網路連接的,例如只要輸入帳號密碼正確就可以拿到正確的私鑰,這就是交易所的錢包,沒錯他是熱錢包,所以也是最不安全的錢包。

反之越不常接觸網路的私鑰就越是偏冷的私鑰,市面上甚至有實體化的冷錢包,他像USB那樣要插上電腦你才可以拿到他的私鑰,這樣一來除非有人要爬進你家裡拿這台冷錢包,不然基本上他可以進入自己錢包的機率是零。

所以換個角度想,越冷的錢包似乎就單純只是保管私鑰的方式有沒有一直在接觸網路,這樣想是對的,但不要對交易所的熱錢包太過於恐慌,因為不論擺在網路的哪,最重要的是放在一個駭客極難入侵的地方就好,這就是為什麼大多交易所都極度建議要有雙重認證的原因。

P.S.這邊就先不贅述公鑰和私鑰是什麼,不只虛擬錢包其實電腦系統很多地方都會用到,上網查就有很多資料。

如何有其他種類的錢包

除了交易所我們如何創造自己的錢包?

其實創造錢包是極其容易而且是可以一直創造的,直接介紹手機和電腦最簡單的工具:

1.在chrome遊覽器的MetaMask

2.在手機app的imToken

如果你真的想了解每一筆交易更多的資訊極度建議可以創造這種錢包放一點小錢去做研究,通常台灣的交易所給的訊息很少,尤其是發送交易的時候不能自己設定Gas fee(後面會提到),但當然不熟操作的可以只放一點點錢就好甚至MetaMask有測試版的以太幣可以領,連結在這邊。

如何發起交易廣播

交易廣播其實就是區塊鏈發起每一筆交易會做的事情,因為區塊鏈是全世界一起共同維護的帳本,所以發起的交易一定要是大家都知道才行。

區塊鏈的發起交易很簡單,每個錢包都有自己的地址只要進入自己的錢包後傳給對方的地址就好。

在這途中會發生一件事情是有Gas fee這個東西,剛剛說我們的每一筆交易是全世界維護的,但其實是專門有人下載程式在幫我們跑這些計算,這些人就稱為礦工,他們是要收取手工費(Gas fee)的!

大多的交易所不能設Gas fee,這是蠻重要的一點,當然Gas fee設定的越高交易越容易成功,另外還有一點很重要的是失敗的交易單Gas fee是不退還的,所以當緊急情況例如要大漲或大跌的時候因為一次太多人發起交易廣播會造成礦工來不及算,這就是交易堵塞,此時建議可以將Gas limit 和 Gas Price分別設定150000 和25,機率和速度會改善很多。

上課心得

猜咖啡的環境還不錯~重點這場是Nic親自出錢包的真的是太狂,畢竟他一開始的簡報開宗道明就是希望這方面的智障少一點XDDDD。

不過讓我很驚訝的是整場下來其實都抓得住我的注意力,即使我沒做筆記隔天才寫這篇心得也還記得昨天大多數在講什麼重點,遠端演講可以有這種程度已經很厲害,不愧是有受過講課訓練的人。

後面閒聊之餘還教我們怎麼用DDOS攻擊別人網站,這次算是很圓滿落幕~

[JavaScript]dataURL轉換Blob 並用 formdata上傳

發表於 2017-09-18 更新於 2019-08-28 分類於 JavaScript

繼上一篇[Vue2]使用vue-avatar-editor套件裁減照片做出大頭貼(Resize image),這次我要做的是用form-data把我的出圖傳上去,但裁剪後得出圖格式是dataURL,而要上傳的格式要是Blob,該如何實現呢?

注意事項:
1.有import jQuery
2.有import axios

dataURL to Blob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var imgURL = $('.someCanvas').toDataURL("image/png");
//直接複製國外的function
dataURItoBlob: function (dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);

// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);

// create a view into the buffer
var ia = new Uint8Array(ab);

// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}

// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;

}
var imgBlob = this.dataURItoBlob(imgURL);
//到這邊我們已經製造好blob,開始製造formdata
var postData = new FormData();
postData.append('key', imgBlob, 'fileName.jpg' );
//最後一個參數是可以自行設定檔案名稱
axios.post('url', postData, {'content-type': 'multipart/form-data'})
.then( function (response) {
//handle succeed
}).catch(function (error) {
//handle error
})

這樣就能利用dataURL上傳Blob格式囉!

參考文件

image 各種型態轉換(blob, dataURL, canvas) in JavaScript

stackoverflow-Blob from DataURL?

stackoverflow-How to give a Blob uploaded as FormData a file name?

[JavaScript]Do not scroll parent element

發表於 2017-09-18 更新於 2019-08-21 分類於 JavaScript

正常來講滑完子元素的滾輪他會自動滑外面父元素的滾輪,要取消的話只要加上一段js就可以了:

1
2
3
4
5
6
7
$( '.son' ).on( 'mousewheel', function ( e ) {
var event = e.originalEvent,
d = event.wheelDelta || -event.detail;

this.scrollTop += ( d < 0 ? 1 : -1 ) * 10;
e.preventDefault();
});

比較有趣的是this.scrollTop += ( d < 0 ? 1 : -1 ) * 10;後面的* 10似乎會影響滑動速度,調越高滑越快,還沒有很搞懂這個原理之前先把它記下來。

參考文件
某一個人的Stack overflow

某人的codepen也很值得研究

[Vue2]使用vue-avatar-editor套件裁減照片做出大頭貼(Resize image)

發表於 2017-09-15 更新於 2019-08-21 分類於 Vue2

如果對於canvas熟悉的人不一定要使用這個套件,畢竟我是因為這個套件才認識了幾本的canvas用法,畢竟他的文檔沒有更多後續的資訊,vue-avatar-editor的Github。

使用前須知:

  1. 不用npm install這個套件只需自行創造這兩個.vue檔案import到使用的地方就好。
  2. 這個團隊似乎沒在維護這個Github了,有個簡單的錯誤tag <canvas> has no matching end tag.也沒修,自行到VueAvatar.vue這個檔案的template裡面幫他加上去</canvas>即可。

如何簡單使用vue-avatar-editor:

他的屬性真的不多,文件上就可以輕鬆掌握,裁減之後會觸發他預設的saveClicked(),他會給我們一個變數名稱是一個canvas的tag,然後呢?然後他的文件就到此為止了XD。

但其實這就是出圖的東西囉!!我們需要把這張圖片變成程式碼格式,其中一種格式只要下var pictureURL = img.toDataURL("image/png");再把他console.log出來會發現是一堆人看不懂的字串,但是電腦是看得懂的!

接著只要創造一個img的tag去裝他就行了!只要下這行$('.picture').attr('src', imgURL);就可以看到才剪出來的圖片了!

直接看範例吧:
p.s:我有用到jQuery喲!
先看html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
<vue-avatar
:width=400
:height=400
ref="vueavatar"
@vue-avatar-editor:image-ready="onImageReady"
image="https://vuejs.org/images/logo.png"
>
</vue-avatar>
<br>
<vue-avatar-scale
ref="vueavatarscale"
@vue-avatar-editor-scale:change-scale="onChangeScale"
:width=250
:min=1
:max=3
:step=0.02
>
</vue-avatar-scale>
<br>
<img src="" id="img-1">
<button v-on:click="saveClicked">Click</button>
<img src="#" class="picture">
</div>

看看JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Vue from 'vue'
import VueAvatar from './components/VueAvatar.vue'
import VueAvatarScale from './components/VueAvatarScale.vue'

let vm = new Vue({
el: '#app',
components: {
VueAvatar,
VueAvatarScale
},
methods:{
onChangeScale (scale) {
this.$refs.vueavatar.changeScale(scale)
},
saveClicked(){
var img = this.$refs.vueavatar.getImageScaled()
// use img
var pictureURL = img.toDataURL("image/png");
$('.picture').attr('src', imgURL);
},
onImageReady(scale){
this.$refs.vueavatarscale.setScale(scale)
}
}
})

沒意外的話就可以把img做出來了

Canvas與Image可以互相轉換:

這個網站有最簡單的function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//用<img>製作一個新的<canvas>
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);

return canvas;
}
//用<canvas>製作一個新的<img>
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}

單純的互相轉換其實沒有這麼複雜,網路上有一堆文章幾乎都寫得大同小異,最常看到應該是使用filereader,filereader可以處理更多種類的檔案還有狀態,但我這裡不需要這麼複雜的操作。

只是因為需要做裁減的動作的話必須熟悉Canvas,但既然我們都沒有這麼多時間的話vue-avatar-editor確實幫我們做好了,所以vue-avatar-editor搭配這個網站的簡述就可以簡易做出大頭貼囉!

參考文章

vue-avatar-editor
Convert an Image to Canvas with JavaScript

1…91011…18

Kurt Hsu

Progress One Percent Every Day
171 文章
55 分類
163 標籤
RSS
© 2020 Kurt Hsu
由 Hexo 強力驅動 v3.8.0
|
主題 – NexT.Muse v7.3.0