Skip to content

Instantly share code, notes, and snippets.

@oreshinya
Last active December 29, 2015 09:59
Show Gist options
  • Select an option

  • Save oreshinya/7653921 to your computer and use it in GitHub Desktop.

Select an option

Save oreshinya/7653921 to your computer and use it in GitHub Desktop.
step-startなどのstep実行用のkeyframeからlinearでstep実行っぽく見せるkeyframeの生成
require 'sass'
BASE_SCSS_LOAD_PATH = './assets/www/app/stylesheets/main.css.scss'
KEYFRAMES_OUTPUT_PATH = "./assets/www/app/stylesheets/android_keyframes.css.scss"
class Sass::Tree::Visitors::ToArray < Sass::Tree::Visitors::Base
protected
def initialize
@array = []
end
def visit(node, parent = false)
if node_name(parent) == "root"
@media = "all"
end
method = "visit_#{node_name(node)}"
if self.respond_to?(method, true)
self.send(method, node)
else
visit_children(node)
end
@array
end
def visit_children(parent)
parent.children.map {|c| visit(c, parent)}
end
def visit_root(node)
visit_children(node)
end
def visit_media(node)
@media = node.query.join('')
visit_children(node)
end
def visit_rule(node)
@selector = node.rule[0]
visit_children(node)
end
def visit_prop(node)
return unless node.value
@array << {
media: @media,
selector: @selector,
property: node.name[0],
value: node.value.to_sass
}
end
end
class Sass::Tree::Node
def to_a
Sass::Tree::Visitors::ToArray.visit(self)
end
end
# step-startが登録されているkeyframeを抽出する -webkit-animation-nameなどにわけて書いてる場合 => 一旦非対応
#key_names = []
#engine = Sass::Engine.for_file('./assets/www/app/stylesheets/main.css.scss', {:syntax => :scss})
#scss_array = engine.to_tree.to_a
#animation_selectors = []
#scss_array.each do |a|
# animation_selectors << a if a[:property] == "-webkit-animation-name"
#end
#scss_array.each do |a|
# animation_selectors.each do |s|
# if s[:selector] == a[:selector] && a[:property] == "-webkit-animation-timing-function" && a[:value].include?("step")
# key_names << s[:value]
# end
# end
#end
#p key_names.flatten
# step-startが登録されているkeyframeを抽出する -webkit-animation記法
engine = Sass::Engine.for_file(BASE_SCSS_LOAD_PATH, {:syntax => :scss})
scss_array = engine.to_tree.to_a
scss_using_step = scss_array.select do |a|
a[:value].include?("step")
end
key_names_using_step = scss_using_step.map do |scss|
match = scss[:value].scan(/^.*? /)
match << scss[:value].scan(/,.*? /)
match << scss[:value].scan(/, .*? /)
end.flatten.map do |str|
key_name = str.gsub(/ /, "").gsub(/,/, "")
next if key_name == ""
key_name
end.uniq
p key_names_using_step
# android用keyframesの出力のためのデータ整形
results = []
engine = Sass::Engine.for_file(BASE_SCSS_LOAD_PATH, {:syntax => :scss})
tree = engine.to_tree
tree.each do |node|
if node.class == Sass::Tree::DirectiveNode && node.name == "@-webkit-keyframes" && key_names_using_step.include?(node.value[1])
data = {name: node.name, key_name: node.value[1], frames: {}}
node.children.each do |c_node|
data[:frames][c_node.rule[0].to_s] = [] if c_node.respond_to?(:rule)
if c_node.has_children
c_node.children.each do |cc_node|
property_value = nil
if cc_node.respond_to?(:name)
if cc_node.class == Sass::Tree::PropNode
property_value = cc_node.name[0] + ": " + cc_node.value.to_sass
elsif cc_node.class == Sass::Tree::MixinNode
property_value = "@include " + cc_node.name + "("+cc_node.args.join(",")+")"
end
data[:frames][c_node.rule[0].to_s] << property_value if !property_value.nil?
end
end
end
end
results << data
end
end
p results
# android_keyframes.css.scssの生成 以下のscriptはstep-end用のkeyframesが生成されるようになってる
# データは以下のような感じ
#[{:name=>"@-webkit-keyframes", :key_name=>"\"display_tap_action\"", :frames=>{"0%"=>["bg_image_set(50px,50px,\"../../img/icon/display_tap_action_1@2x.png\")"], "25%"=>["bg_image_set(50px,50px,\"../../img/icon/display_tap_action_2@2x.png\")"], "50%"=>["bg_image_set(50px,50px,\"../../img/icon/display_tap_action_3@2x.png\")"], "75%"=>["bg_image_set(50px,50px,\"../../img/icon/display_tap_action_4@2x.png\")"], "100%"=>["bg_image_set(50px,50px,\"../../img/icon/display_tap_action_5@2x.png\")"]}}]
scss_string = ""
results.each do |result|
str = "#{result[:name]} #{result[:key_name]} {\n"
result[:frames].keys.each_cons(2) do |key, next_key|
str += " #{key} {\n"
result[:frames][key].each do |property_value|
str += " #{property_value};\n"
end
str += " }\n"
if next_key == "to"
next_key_f = 100.0
else
next_key_f = next_key.gsub(/%/, "").to_f
end
next_key_f = next_key_f - 0.0001
key_for_step = next_key_f.to_s + "%"
str += " #{key_for_step} {\n"
result[:frames][key].each do |property_value|
str += " #{property_value};\n"
end
str += " }\n"
end
key = result[:frames].keys[-1]
str += " #{key} {\n"
result[:frames][key].each do |property_value|
str += " #{property_value};\n"
end
str += " }\n"
str += "}\n"
scss_string += str
end
File.open(KEYFRAMES_OUTPUT_PATH, "w") do |file|
file.puts scss_string
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment